涉及日期范围计算的复杂查询

时间:2011-10-06 14:53:23

标签: sql sql-server sql-server-2008

我有一个数据库中多家公司的备份详细信息列表。以下是它的设置方法(大致):

字段:

ID
Company (nvarchar)
Servername (nvarchar)
Finaljobstatus (nvarchar)
actualstarttime (datetime)
endtime (datetime)
totaldatasizebytes (nvarchar)
tasktypeid (nvarchar)

公司可能在数据库中有数百行。我想知道我是否可以在SQL查询中直接做我需要做的事情,在逻辑上:

  1. 计算出第一次记录的备份和最后记录的备份之间的天数(可以使用实际的启动时间)

  2. 计算出这两条记录之间的totaldatasizebytes差异

  3. 每天平均增加

  4. 以上所有内容都应该在finaljobstatus = 19或finaljobstatus = 3且tasktypeid = 100

  5. 时发生

    我意识到这变得更加困难,因为设计这个的人使数字字段成为nvarchars,但是这个查询超出了我,所以任何帮助都会非常感激。

2 个答案:

答案 0 :(得分:1)

这将为您提供第1部分的答案。

select
  Company,
  min(actualstarttime),
  max(actualstarttime)
from
  mytable
where
  finaljobstatus = 19 or (finaljobstatus = 3 and tasktypeid = '100')
group by
  Company

然后可以将其扩展为提供其他详细信息。将中间结果存储在临时表中可能更容易:

select
  Company,
  minID = min(ID),
  maxID = max(ID)
into
  #t
from
  mytable
where
  finaljobstatus = 19 or (finaljobstatus = 3 and tasktypeid = '100')
group by
  Company

使用此临时表,您可以回答问题1 - 3

select
  #t.Company,
  answer1 = datediff(d, tMin.actualstarttime, tMax.actualstarttime),
  answer2 = (convert(bigint, tMax.totaldatasizebytes) - convert(bigint, tMin.totaldatasizebytes),
  answer3 = (convert(bigint, tMax.totaldatasizebytes) - convert(bigint, tMin.totaldatasizebytes) / datediff(d, tMin.actualstarttime, tMax.actualstarttime)
from
  #t
  inner join mytable tMin
    on #t.minID = tMin.ID
  inner join mytable tMax
    on #t.maxID = tMax.ID

完成后请记得放下临时抽屉

drop table #t

答案 1 :(得分:0)

我开始考虑它并想知道是否有一种方法可以简化它并且没有临时表。因为我最近一直在做的所有事情似乎都涉及CTE,所以我在这条路线上制定了一个解决方案。这是结果,它可能不是从CTE角度来看它的最有效的方法,但我更喜欢它到一堆临时表,它使大部分讨厌的演员离开最后的SELECT:< / p>

   ;WITH CompanyDays
AS (
    SELECT
        Company
        ,MIN(ActualStartTime) AS StartDate
        ,MAX(endtime) AS EndDate
    FROM Companies
    WHERE finaljobstatus = '19' OR (finaljobstatus = '3' AND tasktypeid = '100')
    GROUP BY Company
    )
,StartFileSize
AS
(
    SELECT 
            c.Company
            ,c.totaldatasizebytes AS StartFileSize
            ,cd.StartDate
            ,cd.EndDate        
    FROM Companies AS c
    JOIN CompanyDays AS cd ON c.actualstarttime= cd.StartDate
    WHERE (finaljobstatus = '19' OR (finaljobstatus = '3' AND tasktypeid = '100'))
)
,EndFileSize
AS
(
    SELECT 
            c.Company
            ,CAST(s.StartFileSize AS DECIMAL(18,0)) AS StartFileSize
            ,CAST(c.totaldatasizebytes AS DECIMAL(18,0)) AS EndFileSize
            ,DATEDIFF(dd,cd.StartDate,cd.EndDate) AS DayDiff
            ,CAST(c.totaldatasizebytes AS DECIMAL(18,0)) - CAST(s.StartFileSize AS DECIMAL(18,0)) AS FileDiff
            ,cd.StartDate
            ,cd.EndDate        
    FROM Companies AS c
    JOIN CompanyDays AS cd ON c.endtime= cd.EndDate
    JOIN StartFileSize AS s ON c.Company = s.Company
    WHERE (finaljobstatus = '19' OR (finaljobstatus = '3' AND tasktypeid = '100'))
)


SELECT 
    e.Company
    ,DayDiff
    ,FileDiff
    ,(FileDiff/e.StartFileSize)/DayDiff AS AveragePercentageChange
FROM EndFileSize AS e

请注意,实际开始日期和结束日期的DATEDIFF可能会略微偏差,因为它只计算跨越的实际日界限(即午夜)。在大多数情况下,这将是完美的。如果没有,你可以在几小时内采取另一种措施,如约会,并将结果除以24;分钟并将它除以1440;秒数除以86400,具体取决于你需要多大精确的日差。

编辑:我意识到我的数学已经完成了。如果这两天之间有所减少怎么办?修复了这个问题并将更多的投射移入了CTE。

相关问题