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