【问题标题】:Optimize SQL query that uses multiple SELECT statements and returns one result set优化使用多个 SELECT 语句并返回一个结果集的 SQL 查询
【发布时间】:2016-01-14 09:41:46
【问题描述】:

我有一个查询,它使用包含不同 WHERE 子句的多个 SELECT 语句来返回多个列,这些列获取不同类别的订单计数。我目前正在使用 cte 来尝试优化它,但它仍然运行得很慢。我认为临时表可能是一个更快的解决方案,但我无法到达那里:

查询:

DECLARE @User AS VARCHAR(50)
SET @User = 'test.user';

WITH cte AS (
SELECT 
    o.db_OrderNo,
    o.db_Deferral,
    d.db_SeqNo,
    d.db_Task
FROM
    tblOrders o
    LEFT JOIN tblDate d on d.db_SeqNo = o.db_Status
    LEFT JOIN tblUserProfile up on up.db_UserId = o.db_RTS
WHERE
    o.db_Deleted = 0
    AND db_Date39 = '1900/01/01' 
    AND d.db_Task IN (1, 2, 3, 4)
    AND up.db_Email LIKE @User + '%'
)
SELECT
(SELECT COUNT(DISTINCT db_OrderNo) 
  FROM cte 
  WHERE db_Task = 1
  AND db_Deferral = 0) OrderInEvalCount,
(SELECT COUNT(DISTINCT db_OrderNo) 
  FROM cte 
  WHERE db_Task = 2
  AND db_Deferral = 0) OrderInDfcCount,
(SELECT COUNT(DISTINCT db_OrderNo) 
  FROM cte 
  WHERE db_Task IN (3, 4) 
    AND db_SeqNo NOT IN (37, 39)
    AND db_Deferral = 0) OrderWipCount,
(SELECT COUNT(DISTINCT db_OrderNo) 
  FROM cte 
  WHERE db_Deferral != 0) OrderInPendedCount

输出:

OrderInEvalCount | OrderInDfcCount | OrderWipCount | OrderInPendedCount
       20                  34              9                  2

临时表:

CREATE TABLE #TempCounts ( OrderInEvalCount int, OrderInDfcCount int, OrderWipCount int, OrderInzPendedCount int);

// First column

SELECT COUNT(DISTINCT db_OrderNo)
  INTO //Not sure how to specify a column
  FROM tblOrders o
  WHERE db_Task = 1
  AND db_Deferral = 0
  AND o.db_Deleted = 0
  AND db_Date39 = '1900/01/01'
  AND up.db_Email LIKE @User + '%'

我以前没有使用过 TEMP 表,所以这个开始可能有点偏离。您认为可以加快当前查询的任何其他解决方案将不胜感激。谢谢

【问题讨论】:

    标签: sql sql-server performance sql-server-2008 temp-tables


    【解决方案1】:

    外部选择可以使用条件聚合:

    SELECT COUNT(DISTINCT (CASE WHEN db_Task = 1 AND db_Deferral = 0 THEN db_OrderNo
                           END)) as OrderInEvalCount,
           COUNT(DISTINCT (CASE WHEN db_Task = 2 AND db_Deferral = 0 THEN db_OrderNo
                           END)) as OrderInDfcCount,
           COUNT(DISTINCT (CASE WHEN db_Task IN (3, 4) AND db_SeqNo NOT IN (37, 39) AND
                                     db_Deferral = 0 THEN db_OrderNo
                           END)) as OrderWipCount,
           COUNT(DISTINCT (CASE WHEN db_Deferral <> 0 THEN db_OrderNo
                           END)) as OrderInPendedCount
    FROM cte;
    

    SQL Server 以特定方式处理 CTE:它将 CTE 的定义插入到查询中它看到的每个位置。因此,您的版本运行 CTE 的代码四次。尽管 SQL Server 随后可以优化查询,但它不能识别出四个块在做同样的事情。 . .所以它做了更多的工作。

    当 CTE 在查询中仅被引用一次时,使用 CTE 对性能没有影响。

    【讨论】:

    • 是的,这也有效...不知道您可以像这样将表达式放入计数中...每天学习一些东西
    • 像魅力一样工作,谢谢!在第二个CASEdb_Deferral = 0 之后有一个额外的括号。我无法进行单字符编辑。
    【解决方案2】:

    我建议处理查询,以便可以将其分组到 db_OrderNo 以删除不同的。

    然后,您的 select 子句可以对整个不同订单号的案例语句求和。

    select sum(case when db_Task = 1 and db_Deferral = 0 then 1 else 0 end) OrderInEvalCount
         , sum(case when db_Task = 2 and db_Deferral = 0 then 1 else 0 end) OrderInDfcCount
         , sum(case when db_Task in (3, 4) and db_SeqNo not in (37, 39) and db_Deferral = 0 then 1 else 0 end) OrderWipCount
         , sum(case when db_Deferral != 0 then 1 else 0 end) OrderInPendedCount
    

    【讨论】:

      猜你喜欢
      • 2020-04-08
      • 2021-06-02
      • 2017-03-13
      • 2017-01-10
      • 1970-01-01
      • 2022-11-21
      • 1970-01-01
      • 1970-01-01
      • 2012-03-30
      相关资源
      最近更新 更多