如何优化SQL查询以实现最短的执行时间

如何优化SQL查询以实现最短的执行时间,sql,sql-server-2008,tsql,stored-procedures,Sql,Sql Server 2008,Tsql,Stored Procedures,我有一个简单的表格“table_1” Org Customer Code Ordered Deleted Confirmed RU Cust_1 A 1000 800 200 RU Cust_2 B 300 0 300 US Cust_3 C 800 100 700 RU Cust_4

我有一个简单的表格“table_1”

Org   Customer   Code   Ordered   Deleted   Confirmed

RU     Cust_1      A      1000       800        200 
RU     Cust_2      B      300        0          300
US     Cust_3      C      800        100        700
RU     Cust_4      B      100        100        0
US     Cust_5      C      400        200        200 
RU     Cust_6      B      500        300        200   
现在,我需要为这些行转换此表,其中“已删除”0类似

我正在使用以下查询和函数

SELECT T1.Org,
       T1.Code,
       dbo.FUNC(T1.Code, T1.Org) AS 'Customers',
       'Ordered' = (SELECT SUM(Ordered) FROM TABLE_1 AS T2 WHERE T2.Customer = T1.Customer AND T2.Code = T1.Code AND T2.Deleted<>0),
       'Confirmed' = (SELECT SUM(Confirmed) FROM TABLE_1 AS T3 WHERE T3.Customer = T1.Customer AND T3.Code = T1.Code AND T3.Deleted<>0)
FROM TABLE_1 AS T1 
WHERE T1.Deleted <> 0

无论您选择做什么,都将面临RBAR问题。 然而,您可能会发现使用XML PATH+EXTER APPLY比使用函数更好

如果您不知道这些,我将编写一段代码来演示其用法。 但是您可以先提供表DDL+一些行吗

这是:

SELECT
    T1.Org
    , T1.Code
    , ISNULL(STUFF(F.Customers, 1, 2, ''), '')  AS Customers
    , SUM(T1.Ordered) OVER (PARTITION BY T1.Customer, T1.Code) AS Ordered
    , SUM(T1.Confirmed) OVER (PARTITION BY T1.Customer, T1.Code) AS Confirmed
FROM TABLE_1 AS T1
OUTER APPLY (
    SELECT
        ', ' + T2.Customer
    FROM TABLE_1 AS T2
    WHERE T2.Code = T1.Code
    AND T2.Org = T1.Org
    AND T2.Deleted <> 0
    FOR XML PATH('')
) AS F(Customers)
WHERE T1.Deleted <> 0

最好的方法可能需要对您的特定数据进行一些测试,但首先,让我们修复您的原始查询,以获得您在问题中所写的正确结果:

SELECT T1.Org,
       T1.Code,
       dbo.FUNC(T1.Code, T1.Org) AS Customers,
       SUM(Ordered) AS Ordered,
       SUM(Confirmed) AS Confirmed
FROM TABLE_1 AS T1 
WHERE T1.Deleted <> 0
GROUP BY T1.Org, T1.Code

您可以这样做,即使您的客户名称包含XML控件字符,这也应该可以

就性能而言,只需执行两个查询并担心以后以逗号分隔的列表的形式显示是有意义的。您可以获得相同的信息,但没有MSSQL无法实现的字符串聚合开销


实际上,您想在TSQL中连接字符串,是不是没有表示层?我不确定我是否理解您的意思。我应该在查询中使用连接而不是函数吗?对于同一客户、组织和代码,是否可能有多行?如果是这样的话,到目前为止提供的大多数答案在没有针对不同客户进行某些修复的情况下都无法正常工作。而且根据我的测试,您的功能在速度上仍然优于提供的两个答案。@mbigun,我已经扩展了我的答案来说明我的意思。MSSQL在字符串连接方面真的很糟糕,在MSSQL中执行该操作是必要的吗?谢谢!如果您能提供一些CTE解决方案的示例,我将不胜感激。对不起,CTE只会让查询实际运行得很糟糕,因为它依赖于行数,而其中的PARTITION BY子句不会帮助MSSQL避免进行完全扫描。抱歉,在我的版本之前,我甚至谈到了CTE。请注意,这并不能给出正确的结果,但即使修复,实际执行时间也比原始函数差10倍。mbigun不会在查询中分组行,但您的假设对他来说也是正确的。
CREATE TABLE [dbo].[TABLE_1](
[Org] [nchar](10) NULL,
[Customer] [nchar](100) NULL,
[Code] [nchar](10) NULL,
[Ordered] [decimal](18,1) NULL,
[Deleted] [decimal](18,1) NULL,
[Confirmed] [decimal](18,1) NULL) 
ON [PRIMARY]
SELECT
    T1.Org
    , T1.Code
    , ISNULL(STUFF(F.Customers, 1, 2, ''), '')  AS Customers
    , SUM(T1.Ordered) OVER (PARTITION BY T1.Customer, T1.Code) AS Ordered
    , SUM(T1.Confirmed) OVER (PARTITION BY T1.Customer, T1.Code) AS Confirmed
FROM TABLE_1 AS T1
OUTER APPLY (
    SELECT
        ', ' + T2.Customer
    FROM TABLE_1 AS T2
    WHERE T2.Code = T1.Code
    AND T2.Org = T1.Org
    AND T2.Deleted <> 0
    FOR XML PATH('')
) AS F(Customers)
WHERE T1.Deleted <> 0
SELECT
   Org,
   Code,
   STUFF(
      (SELECT ','+Customer
       FROM t WHERE Code=a.Code and Deleted<>0
       FOR XML PATH('')) , 1 , 1 , '' ),
   SUM(ordered),
   SUM(Confirmed) 

FROM 
   t A 
where Deleted<>0
group by ORG,code
SELECT T1.Org,
       T1.Code,
       dbo.FUNC(T1.Code, T1.Org) AS Customers,
       SUM(Ordered) AS Ordered,
       SUM(Confirmed) AS Confirmed
FROM TABLE_1 AS T1 
WHERE T1.Deleted <> 0
GROUP BY T1.Org, T1.Code
SELECT
            t1.[Org],
            t1.[Code],
            STUFF(
                (
                 SELECT
                               ', ' + c.[Customer]
                     FROM
                               [TABLE_1] c
                     WHERE
                               c.[Deleted] <> 0
                         AND
                               c.[Org] = t1.[Org]
                         AND
                               c.[Code] = t1.[Code]
                     ORDER BY
                               c.[Customer]
                     FOR XML PATH (''), TYPE
                 ).value('.', 'varchar(max)'),
                 1,
                 2,
                 '') [Customers],
            SUM(t1.[Ordered]),
            SUM(t1.[Confirmed])
    FROM
            [TABLE_1] t1

    WHERE
            t1.[Deleted] <> 0
    GROUP BY
            t1.[Org],
            t1.[Code];
SELECT
            t1.[Org],
            t1.[Code],
            SUM(t1.[Ordered]),
            SUM(t1.[Confirmed])
    FROM
            [TABLE_1] t1

    WHERE
            t1.[Deleted] <> 0
    GROUP BY
            t1.[Org],
            t1.[Code];

SELECT
            t1.[Org],
            t1.[Code],
            t1.[Customer]
    FROM
            [TABLE_1] t1

    WHERE
            t1.[Deleted] <> 0
    ORDER BY
            t1.[Org],
            t1.[Code],
            t1.[Customer];