【问题标题】:SQL Query taking long time with STUFF function使用 STUFF 函数需要很长时间的 SQL 查询
【发布时间】:2015-10-23 18:21:00
【问题描述】:

示例数据集:

ID  seat    code
15098   1   AA21
15098   2   AA21
15105   1   AA21
15105   1   DD15
15105   1   NN60
15196   1   AA21
15196   2   DD50
15196   2   DD51
15209   1   AA21
15209   3   AA21
15209   2   CC50
15209   1   DD01
15209   3   DD01
15210   1   AA21
15210   2   AA21
15210   3   AA21
15210   1   DD21
15210   2   DD21
15210   3   DD21
15211   1   CC51
15211   1   DD20
15212   1   AA21
15212   1   DD03

而期望的结果是:

ID  seat    Codes
15098   1    AA21
15098   2    AA21
15105   1    AA21, DD15, NN60
15196   1    AA21
15196   2    DD50, DD51
15209   1    AA21, DD01
15209   2    CC50
15209   3    AA21, DD01
15210   1    AA21, DD21
15210   2    AA21, DD21
15210   3    AA21, DD21
15211   1    CC51, DD20
15212   1    AA21, DD03

示例数据集表查询:

CREATE TABLE #Temp(
ID varchar(50),
seat varchar(50), 
code varchar(150))

INSERT INTO #Temp VALUES ('15098', '1', 'AA21');
INSERT INTO #Temp VALUES ('15098', '2', 'AA21');
INSERT INTO #Temp VALUES ('15105', '1', 'AA21');
INSERT INTO #Temp VALUES ('15105', '1', 'DD15');
INSERT INTO #Temp VALUES ('15105', '1', 'NN60');
INSERT INTO #Temp VALUES ('15196', '1', 'AA21');
INSERT INTO #Temp VALUES ('15196', '2', 'DD50');
INSERT INTO #Temp VALUES ('15196', '2', 'DD51');
INSERT INTO #Temp VALUES ('15209', '1', 'AA21');
INSERT INTO #Temp VALUES ('15209', '3', 'AA21');
INSERT INTO #Temp VALUES ('15209', '2', 'CC50');
INSERT INTO #Temp VALUES ('15209', '1', 'DD01');
INSERT INTO #Temp VALUES ('15209', '3', 'DD01');
INSERT INTO #Temp VALUES ('15210', '1', 'AA21');
INSERT INTO #Temp VALUES ('15210', '2', 'AA21');
INSERT INTO #Temp VALUES ('15210', '3', 'AA21');
INSERT INTO #Temp VALUES ('15210', '1', 'DD21');
INSERT INTO #Temp VALUES ('15210', '2', 'DD21');
INSERT INTO #Temp VALUES ('15210', '3', 'DD21');
INSERT INTO #Temp VALUES ('15211', '1', 'CC51');
INSERT INTO #Temp VALUES ('15211', '1', 'DD20');
INSERT INTO #Temp VALUES ('15212', '1', 'AA21');
INSERT INTO #Temp VALUES ('15212', '1', 'DD03');

我使用下面的查询作为我的 SSRS 报告存储过程的一部分来获取结果,但运行时间太长,因为我的原始数据集超过 100000 行。有没有其他有效的方法来获得结果。

SELECT 
 SS.ID
,SS.seat
,STUFF((SELECT ', ' + CAST(LTRIM(RTRIM(CR.Code)) AS VARCHAR(10)) [text()]
        FROM #Temp CR 
        WHERE CR.ID = SS.ID and CR.seat = SS.seat
        FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,2,' ') Codes
FROM #Temp SS
GROUP BY SS.ID, SS.seat

【问题讨论】:

  • 您有IDseat 的索引吗?这会有所帮助
  • 我的实际查询中的#temp 是一个不是索引视图的视图。
  • 基础表上是否有索引?这将在查询处理中得到扩展。检查实际的执行计划以了解所有时间的去向。
  • 我检查了视图的执行计划,它建议在其中一个基础表上有一个非聚集索引,但问题是我们不允许在数据库上创建任何索引,因为它是公司与软件供应商的 SLA。我不确定如何解决这个问题。
  • 值得将数据推送到临时表或表变量中,建立索引,然后进行查询。可能会更慢,可能会更快,值得一试。如果几乎所有行都只有一个代码,您可以尝试拆分为 CASE 或 UNION,这样您就只在需要它的东西上运行 XML PATH……但这似乎不应该更好。

标签: sql sql-server tsql reporting-services sql-server-2012


【解决方案1】:

尝试使用Cross Apply 而不是Correlated Sub-Query

SELECT SS.ID,
       SS.seat,
       LEFT(cs.Codes, Len(cs.Codes) - 1) AS Region
FROM   #Temp SS
       CROSS APPLY (SELECT Code + ','
                    FROM   #Temp CR
                    WHERE  CR.ID = SS.ID
                           AND CR.seat = SS.seat
                    FOR XML PATH('')) cs (Codes)
GROUP  BY SS.ID,
          SS.seat,
          LEFT(cs.Codes, Len(cs.Codes) - 1) 

还在ID and seat 上创建一个Non clustered index,包括code

CREATE NONCLUSTERED INDEX IX_ProductVendor_VendorID
  ON #Temp (ID, seat)
  include (code) 

执行计划

您的查询

使用交叉应用

【讨论】:

    猜你喜欢
    • 2016-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-09
    • 2015-05-17
    相关资源
    最近更新 更多