簡體   English   中英

基於列數據合並sql表的記錄

[英]merging records for sql table based on column data

我在t_resourcetable中有一些骯臟的資源使用記錄,看起來像這樣

resNo   subres    startdate                        enddate
1        2        2012-01-02 22:03:00.000          2012-01-03 00:00:00.000
1        2        2012-01-03 00:00:00.000          2012-01-04 00:00:00.000
1        2        2012-01-04 00:00:00.000          2012-01-04 16:23:00.000
1        3        2012-01-06 16:23:00.000          2012-01-06 22:23:00.000
2        2        2012-01-04 05:23:00.000          2012-01-06 16:23:00.000

我需要這些臟行以這種方式合並

resNo   subres    startdate                        enddate
1        2        2012-01-02 22:03:00.000          2012-01-04 16:23:00.000
1        3        2012-01-06 16:23:00.000          2012-01-06 22:23:00.000
2        2        2012-01-04 05:23:00.000          2012-01-06 16:23:00.000

這應該更新到同一張表,我有超過40k的行,所以不能使用游標,請幫助我通過一些優化的sql語句清理此類數據。

temptable和group提供的解決方案不會遇到類似的情況。 我正在尋找沒有基於游標的解決方案

resNo   subres    startdate                        enddate
1        2        2012-01-02 22:03:00.000          2012-01-03 00:00:00.000
1        2        2012-01-03 00:00:00.000          2012-01-04 00:00:00.000
1        2        2012-01-04 00:00:00.000          2012-01-04 16:23:00.000
1        2        2012-01-14 10:09:00.000          2012-01-15 00:00:00.000
1        2        2012-01-15 00:00:00.000          2012-01-16 00:00:00.000
1        2        2012-01-16 00:00:00.000          2012-01-16 03:00:00.000
1        3        2012-01-06 16:23:00.000          2012-01-06 22:23:00.000
2        2        2012-01-04 05:23:00.000          2012-01-06 16:23:00.000

我需要這些臟行以這種方式合並

resNo   subres    startdate                        enddate
1        2        2012-01-02 22:03:00.000          2012-01-04 16:23:00.000
1        2        2012-01-14 10:09:00.000          2012-01-16 03:00:00.000
1        3        2012-01-06 16:23:00.000          2012-01-06 22:23:00.000
2        2        2012-01-04 05:23:00.000          2012-01-06 16:23:00.000

plesae讓我擺脫了這個骯臟的數據問題

您需要按resNo和subRes對數據進行分組,如下所示:

select resNo, subRes, min(startdate), max(enddate)
from  t_resourcetable
group by resNo, subRes

並將結果插入臨時表中。

然后,您可以截斷t_resourcetable並將臨時模板的結果插入其中

第一步是創建備份:

select * 
into t_resourcetable_backup20120327
from t_resourcetable

然后更新由resNo和subRes分組的第一條記錄的結束日期:

update t_resourcetable
set enddate = (select max (enddate) 
                 from t_resourcetable t1 
                where t1.resNo = t_resourcetable.resNo
                  and t1.subRes = t_resourcetable.subRes)
 where not exists (select null
                 from t_resourcetable t1
                where t1.resNo = t_resourcetable.resNo
                  and t1.subRes = t_resourcetable.subRes
                  and t1.startdate < t_resourcetable.startdate)

最后刪除額外的記錄:

delete t_resourcetable
 where exists (select null
                 from t_resourcetable t1
                where t1.resNo = t_resourcetable.resNo
                  and t1.subRes = t_resourcetable.subRes
                  and t1.startdate < t_resourcetable.startdate)

如果resNo和subRes的唯一組合的開始日期重復,則將保留重復項。 您還應該檢查結束日期是否總是具有相應的開始日期,因為您會失去空白-但這可能只是您想要的。

除了創建備份外,您還可以將更新/刪除包裝在事務中,在刪除和回滾后進行選擇,然后在Excel中檢查數據,如果一切正常,請重復事務但這次進行提交。

更新:此查詢標識差距。 如果您使用的是Sql Server 2000,請將CTE轉換為派生表。 首先返回沒有前任資源的列表,最后返回后繼資源。 兩者都算差距。 然后,列表由resNo,subRes和空位號連接。

;with first as (
    select resNo, subres, startdate,
  row_number() over (partition by resNo, subres order by startdate) rowNumber
      from t_resourcetable
     where not exists (select null
                       from t_resourcetable t1
                      where t1.resNo = t_resourcetable.resNo
                        and t1.subres = t_resourcetable.subres
                        and t1.enddate = t_resourcetable.startdate)
),
last as (
  select resNo, subres, enddate,
  row_number () over (partition by resNo, subres order by enddate) rowNumber
  from t_resourcetable
     where not exists (select null
                       from t_resourcetable t1
                      where t1.resNo = t_resourcetable.resNo
                        and t1.subres = t_resourcetable.subres
                        and t1.startdate = t_resourcetable.enddate)
)
select first.resno, first.subres, first.startdate, last.enddate
from first 
  inner join last
  on first.resNo = last.resNo
    and first.subres = last.subres
    and first.rowNumber = last.rowNumber

你可以試試這個嗎?

SELECT resno,
       subres,
       startdate,
       MIN(enddate) AS enddate
FROM   (SELECT t1.resno,
               t1.subres,
               t1.startdate,
               t2.enddate
        FROM   t_resourcetable t1,
               t_resourcetable t2
        WHERE  t1.enddate <= t2.enddate
               AND NOT EXISTS (SELECT *
                               FROM   t_resourcetable t3
                               WHERE  ( t1.resno = t3.resno
                                        AND t1.subres = t3.subres
                                        AND t1.startdate > t3.startdate
                                        AND t1.startdate <= t3.enddate )
                                       OR ( t2.resno = t3.resno
                                            AND t2.subres = t3.subres
                                            AND t2.enddate >= t3.startdate
                                            AND t2.enddate < t3.enddate )))t
GROUP  BY resno,
          subres,
          startdate 

圖像就像

時間線

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM