2012-03-27 195 views
1

我有一些骯髒的資源使用記錄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帶我離開這個骯髒的數據問題

+0

重複:http://stackoverflow.com/questions/9884642/merging-records-from-multiple-rows-in-table-sql-server – 2012-03-27 17:07:21

回答

0

第一步是創建備份:

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的唯一組合的重複startdates,這將會留下重複項。你還應該檢查enddates是否總是有相應的startdates,因爲你會失去差距 - 但這可能只是你想要的東西。

除了創建備份,您可能會在事務中包裝更新/刪除,在刪除和回滾之後執行選擇,然後檢查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 
+0

這將不會返回資源1和子資源2(從2012年1月1日開始)(2012年1月1日 - 2012年1月1日)/2012)。而這隻會導致連續資源使用的一行(2/1/2012-16/1/2012)感謝您的回覆nikola – 2012-03-27 09:42:43

+0

@ steavefinner我編輯了我的答案。 – 2012-03-27 10:45:42

+0

感謝尼科拉,但我相信這將是非常耗時的... – 2012-03-27 13:06:26

1

的你需要通過resNo和subRes來對你的數據進行分組:

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

並將結果插入臨時表。

然後你就可以截斷t_resourcetable並插入從臨時tample的reult進去

+1

它不會工作,因爲資源1的數據被使用兩次,並且group by將只返回一行,其中resourceno(1)和subres(2) – 2012-03-27 09:13:11

+0

的實際結果應該有兩行,它們按這兩個字段分組: resNo,subRes – Diego 2012-03-27 09:19:31

+0

是的,它是通過將這兩個字段分組resno,subres,通過分組創建兩個diffe創建一個記錄在不同的日期租用兩次相同的資源。理想情況下它應該是兩行 – 2012-03-27 09:22:06

0

你可以試試這個嗎?

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 

的圖像是像

TimeLine