2011-10-06 93 views
0

我有一個數據庫中多個公司的備份詳細信息列表。下面是它是如何設置(大約):涉及計算日期範圍的複雜查詢

領域:

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

公司可以在數據庫中有數百行。我想知道如果我可以做什麼,我需要直接在SQL查詢中做這在邏輯術語:

  1. 制定出第一記錄備份和最後記錄的備份之間的天量(可以使用actualstarttime)

  2. 這兩個記錄

  3. 現在每天

  4. 平均增加上述所有應該只發生時之間totaldatasizebytes制定出區別finaljobstatus = 19或finaljobstatus = 3和tasktypeid = 100

我意識到這一點變得更加困難,因爲誰設計了這個人提出的數字字段nvarchars,但此查詢超出了我,所以任何幫助,將不勝感激。

+0

我們很樂意在[dba.se](http://dba.stackexchange.com/)上解答這些問題。 –

+0

@Nick:這只是SQL。這不是你需要DBA才能回答的問題。 –

+0

@Catcall - 我們歡迎所有SQL問題,尤其是非基礎問題。儘管我們的名字(我們中的一些人正在期待[更改](http://meta.dba.stackexchange.com/q/270/2660)),但我們只是回答任何一種嚴重的數據庫問題,而不僅僅是數據庫行政。 –

回答

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 

記住下降,當你完成

臨時taple
drop table #t 
+0

對於「第1部分的答案」,「max(endtime)」可能是比max(actualstarttime)更好的選擇。很難肯定地說。 –

+0

可能。我不知道OP是否想要開始,或者開始結束。無論哪種方式,我希望說明了原理。一旦每家公司的最小和最大記錄都在臨時表中,您可以提取幾乎所有你想要的數據。 – njr101

+0

您的平均分數總是會產生一個整數,因爲它們是'BIGINT'。例如,如果文件大小從兩個字節變爲兩天之間的9個字節,則您將返回4而不是4.5。 – Wil

0

我開始考慮它,並想知道是否有一種方法來精簡它,並沒有臨時表。由於我最近所做的一切似乎都涉及CTE,所以我制定了一條解決方案。這是結果,它可能不是去了解它從一個CTE角度看,最有效的方式,但我更喜歡一堆臨時表和它的葉子最討厭的鑄造出來的最終SELECT的:

;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中。