Sql-Server

在大約 250 萬行的表中查找缺失的數據間隙

  • April 3, 2017

我在一家經濟諮詢公司工作,我們所有的數據都儲存在 SQL Server 11 (2012) 中。我們的數據基本上由一個日期列、一個原始數據列、幾個計算列和一個列組成,該列有一個短程式碼來區分每組數據和下一組數據。

我們有數千個這樣的集合,它們都載入到同一個表中(總共約 250 萬行),然後從查詢中提取並排序。它們通常按日期排序,從第一個月開始,逐月移動,直到最後一個月。每個系列的開始和結束日期從一年到 100 多年不等。

最近,我們遇到了一些隨機數據部分消失的問題。整行剛起來就離開了,這使得找到這些缺失的行有點挑戰,而不需要每個月都梳理一下是否缺失一個月,這對於一個 250 萬行的表來說是一項不可能完成的任務。

我的老闆要求我編寫一個查詢/儲存過程,該過程將查看這個巨大的表並查看哪些集合缺少行以及它們在哪裡。

我一直在嘗試解決這個問題,這個問題略高於我的 SQL 技能,我似乎無法在網路上的任何地方找到任何遇到類似問題的人。我將經歷我已經擁有的東西,也許有人至少可以告訴我我是否朝著正確的方向前進,並可能提供一些關於我應該從這裡去哪裡的見解。

我可以在網上找到的最佳解決方案是使用 CTE 創建一個臨時日期表,然後將它們與原始表進行比較。如果我只是在一個特定數據集中掃描問題,這非常有用,但是我在同一個表中有許多數據集,所有數據集都有不同的開始和結束日期。所以無論如何我還是選擇了它,希望我最終可以擴展它來搜尋它們中的很多。這是我的程式碼:

declare @startDate Date, @endDate Date 
set @startDate = '2000-01-01'
set @endDate = '2016-11-01'

;with GetDates As  
(  
select @startDate as TheDate
UNION ALL  
select DATEADD(MONTH,1, TheDate) from GetDates
where DATEADD(MONTH,1, TheDate) <= @endDate
)

SELECT TheDate,SHORTCODE,MonthYear 
From GetDates
LEFT OUTER JOIN VWTBL_INDICATOR
ON GetDates.TheDate=VWTBL_INDICATOR.MonthYear
AND VWTBL_INDICATOR.SHORTCODE='RMI WEST'
OPTION(MAXRECURSION 1000)

‘RMI West’ 將是標記此特定數據集的簡碼,它缺少從 2004 年 11 月到 2005 年 3 月的數據,當我執行此查詢時,這些數據顯示為空。這幾乎正是我所需要的,但對於我在表中擁有的每個數據集。

如何正確編寫此查詢?我們公司將我們數據庫上的大量工作外包出去,所以我對它的內容並不十分熟悉。我們有一個上傳功能,當我使用它提取數據時,一切都很好。但是當我在一兩週後查看數據時,它缺少隨機日期。他們一直在尋找解決方案,但同時我們需要一種方法來找到這些差距。

我們將始終檢查幾個月。我們的數據幾乎總是從給定年份的 1 月開始,到當月結束,如果數據還沒有出來,則在當月結束。

我有一個短程式碼的元數據表,但是每個短程式碼的預期月數不包括在內,因為到目前為止我們還沒有使用過這些資訊。我可以詢問添加欄位並修改更新腳本以在更新數據時包含它們,如果這對於使其正常工作至關重要。

我工作的公司歷來將其所有數據儲存在大量 Excel 電子表格中。他們一直在將所有這些數據轉換為 SQL。我的工作是通過各種方法檢查它,以確保 SQL Server 上的數據與原始電子表格中的數據匹配。原始數據可通過我們文件系統上的電子表格網路訪問。在更新數據的時候,我們還是使用 Excel 來更新資訊,然後使用我之前提到的上傳功能在 SQL 中載入。一段時間以來,數據基本上是乾淨和匹配的。僅在過去幾個月中,才出現了這種數據差距問題。

無需生成日期。


以下查詢將為您提供一個沒有行的 SHORTCODES 列表:

select SHORTCODE from shortcodes
except
select SHORTCODE from VWTBL_INDICATOR

以下查詢將為您提供每個 SHORTCODE 的 MonthYear 的連續範圍。

select      SHORTCODE
           ,min(MonthYear) as from_MonthYear
           ,max(MonthYear) as to_MonthYear
           ,count(*)       as months

from       (SELECT   SHORTCODE
                   ,MonthYear
                   ,row_number() over (partition by SHORTCODE order by MonthYear)  as rn

           From     VWTBL_INDICATOR
           ) t

group by    SHORTCODE
           ,DATEADD(month,-rn,MonthYear)   

order by    SHORTCODE
           ,from_MonthYear

如果您願意,可以使用以下具有附加資訊層的版本:

  • missing_from_MonthYear + to_MonthYear:中間缺失範圍
  • 範圍:每個 SHORTCODE 的範圍數(範圍>1 表示中間有間隙)
  • range_seq:每個 SHORTCODE 範圍的序號
  • is_first:每個 SHORTCODE 的第一個範圍的指示(檢查 from_MonthYear 以查看您是否缺少前面的日期)
  • is_last:每個 SHORTCODE 的最後一個範圍的指示(檢查 to_MonthYear 以查看您是否缺少以下日期)

select      SHORTCODE
          ,from_MonthYear                                                                                  as exists_from_MonthYear
          ,to_MonthYear                                                                                    as exists_to_MonthYear
          ,dateadd (day,1,to_MonthYear)                                                                    as missing_from_MonthYear
          ,dateadd (day,-1,lead (from_MonthYear) over (partition by SHORTCODE order by from_MonthYear))    as missing_to_MonthYear
          ,count       (*) over (partition by SHORTCODE)                                                   as ranges
          ,row_number  ()  over (partition by SHORTCODE order by from_MonthYear)                           as range_seq
          ,case from_MonthYear when min(from_MonthYear) over (partition by SHORTCODE) then 1 end           as is_first
          ,case to_MonthYear   when max(to_MonthYear)   over (partition by SHORTCODE) then 1 end           as is_last

from       (select      SHORTCODE
                      ,min(MonthYear)  as from_MonthYear
                      ,max(MonthYear)  as to_MonthYear
                      ,count(*)        as months

           from       (SELECT      SHORTCODE
                                  ,MonthYear
                                  ,row_number() over (partition by SHORTCODE order by MonthYear)   as rn

                       From        VWTBL_INDICATOR
                       ) t

           group by    SHORTCODE
                      ,DATEADD(month,-rn,MonthYear)    
           ) t

order by    SHORTCODE
          ,from_MonthYear

引用自:https://dba.stackexchange.com/questions/159853