优化使用多个SELECT语句并返回一个结果集的SQL查询

时间:2015-10-15 19:26:34

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

我有一个查询,它使用包含不同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表,所以这个开始可能有点偏。您认为可以加快当前查询的任何其他解决方案将不胜感激。感谢

2 个答案:

答案 0 :(得分: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对性能没有影响。

答案 1 :(得分:0)

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

然后你的select子句可以对不同订单号的整个主体中的case语句求和。

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