2015-04-17 160 views
0

我想根據某些列對行進行分組,即如果這些列中的數據在連續行中相同,那麼爲它們分配相同的組號,並且如果其更改,則分配新列。這變得很複雜,因爲列中的相同數據可能會出現在其他某些行中,因此它們必須被賦予另一個組號,因爲它們不在具有前一組的連續行中。 爲了達到這個目的,我使用了cte,並且它也給出了正確的輸出,但速度很慢,因此迭代超過75k +行大約需要15分鐘。我使用的代碼是:遞歸cte工作很慢

WITH 
cte AS (SELECT ROW_NUMBER() OVER (ORDER BY Patient_ID, Opnamenummer, SPECIALISMEN, Opnametype, OntslagDatumTijd) AS RowNumber, 
      Opnamenummer, Patient_ID, AfdelingsCode, Opnamedatum, Opnamedatumtijd, Ontslagdatum, Ontslagdatumtijd, IsSpoedopname, OpnameType, IsNuOpgenomen, SpecialismeCode, Specialismen 
     FROM t_opnames) 

SELECT * INTO #ttt FROM cte; 

WITH cte2 AS (SELECT TOP 1 RowNumber, 
       1 AS GroupNumber, 
       Opnamenummer, Patient_ID, AfdelingsCode, Opnamedatum, Opnamedatumtijd, Ontslagdatum, Ontslagdatumtijd, IsSpoedopname, OpnameType, IsNuOpgenomen, SpecialismeCode, Specialismen 
     FROM #ttt 
     ORDER BY RowNumber 
    UNION ALL 
    SELECT c1.RowNumber, 
      CASE 
       WHEN c2.Afdelingscode <> c1.Afdelingscode 
       OR c2.Patient_ID <> c1.Patient_ID 
       OR c2.Opnametype <> c1.Opnametype 
      THEN c2.GroupNumber + 1 
       ELSE c2.GroupNumber 
      END AS GroupNumber, 
      c1.Opnamenummer,c1.Patient_ID,c1.AfdelingsCode,c1.Opnamedatum,c1.Opnamedatumtijd,c1.Ontslagdatum,c1.Ontslagdatumtijd,c1.IsSpoedopname,c1.OpnameType,c1.IsNuOpgenomen, SpecialismeCode, Specialismen 
    FROM cte2 c2 
    JOIN #ttt c1 ON c1.RowNumber = c2.RowNumber + 1 
    ) 

SELECT * 
    FROM cte2 
    OPTION (MAXRECURSION 0) ; 

DROP TABLE #ttt 

我試圖通過將cte的輸出放在臨時表中來提高性能。這增加了表現,但仍然太慢。那麼,我該如何提高這個代碼的性能到,在10秒鐘內運行75k +記錄呢?取消查詢前的輸出是:Screenshot。從圖像中可以看出,RowNumber 3,5和6中的數據在列Afdelingscode,Patient_ID和Opnametype中是相同的,但由於行的併發,它們具有不同的GroupNumber。

回答

1

沒有數據,它不是那麼容易測試,但我會先嚐試不使用臨時表,只是從頭到尾都使用cte,即;

;WITH 
cte AS (...), 
cte2 AS (...) 
select * from cte2 
OPTION (MAXRECURSION 0); 

不知道指數等......例如,你在第一個cte中做了很多排序。這是由索引(或一個多列索引)支持還是不支持?

沒有這些數據,我沒有選擇用它玩,但看着這樣的:

CASE 
    WHEN c2.Afdelingscode <> c1.Afdelingscode 
     OR c2.Patient_ID <> c1.Patient_ID 
     OR c2.Opnametype <> c1.Opnametype 
      THEN c2.GroupNumber + 1 
    ELSE c2.GroupNumber 

我會嘗試看看partition by聲明ROW_NUMBER

所以嘗試運行此:

WITH 
cte AS (
    SELECT ROW_NUMBER() OVER (PARTITION BY Afdelingscode , Patient_ID ,Opnametype ORDER BY Patient_ID, Opnamenummer, SPECIALISMEN, Opnametype, OntslagDatumTijd) AS RowNumber, 
      Opnamenummer, Patient_ID, AfdelingsCode, Opnamedatum, Opnamedatumtijd, Ontslagdatum, Ontslagdatumtijd, IsSpoedopname, OpnameType, IsNuOpgenomen 
     FROM t_opnames) 
+0

嗨,感謝您的答覆。請看這個小提琴[鏈接](http://sqlfiddle.com/#!6/6aac5/1/0)。我用樣本數據創建了這個小提琴。我無法使用分區,因爲它會對行進行無組織,並且我將不得不在最後一個select語句中再次使用Order By,這會再次降低性能。我已經嘗試過了。 – phreq

+0

在小提琴: 時間與您的解決方案4ms的補臨時表+ 6ms的運行SELECT + 2ms的DROP TABLE(12毫秒計) 時間與您的解決方案,但沒有臨時表:8ms的 時間與分區和ORDER BY:3ms的 請注意即: 小提琴只包含10行。這是一個小數據集。 75k行,執行計劃可以完全不同,所以這不是一個很大的幫助。 看一看,如果你有分區的索引/索引和按列排序,如果是的話,索引是什麼。 此外,請通過解決方案(包括查詢)發佈解決方案的執行計劃和分區。謝謝 –

+0

我在表中有索引,我在列「ID」上有一個聚簇索引。因此,如果我應該在「Order By」列中添加索引,這會很好,集羣還是非集羣? – phreq