2015-04-17 106 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