优化使用多个 SELECT 语句和 returns 一个结果集的 SQL 查询
Optimize SQL query that uses multiple SELECT statements and returns one result set
我有一个查询使用包含不同 WHERE 子句的多个 SELECT 语句到 return 多个列,这些列获得不同类别的订单计数。我目前正在使用 cte 来尝试优化它,但它仍然 运行 非常慢。我认为临时 table 可能是一个更快的解决方案,但我无法做到:
查询:
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
温度Table:
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 tables,所以这个开始可能有点不对劲。您认为可以加快当前查询的任何其他解决方案将不胜感激。谢谢
您可以对外部使用条件聚合 select:
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 服务器以特定方式处理 CTE:它将 CTE 的定义插入到它看到的每个地方的查询中。因此,您的版本为 CTE 运行了四次代码。尽管 SQL 服务器随后可以优化查询,但它无法识别四个块在做同样的事情。 . .所以它做了更多的工作。
当 CTE 在查询中仅被引用一次时,使用 CTE 对性能没有影响。
我建议处理查询,以便它可以在 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
我有一个查询使用包含不同 WHERE 子句的多个 SELECT 语句到 return 多个列,这些列获得不同类别的订单计数。我目前正在使用 cte 来尝试优化它,但它仍然 运行 非常慢。我认为临时 table 可能是一个更快的解决方案,但我无法做到:
查询:
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
温度Table:
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 tables,所以这个开始可能有点不对劲。您认为可以加快当前查询的任何其他解决方案将不胜感激。谢谢
您可以对外部使用条件聚合 select:
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 服务器以特定方式处理 CTE:它将 CTE 的定义插入到它看到的每个地方的查询中。因此,您的版本为 CTE 运行了四次代码。尽管 SQL 服务器随后可以优化查询,但它无法识别四个块在做同样的事情。 . .所以它做了更多的工作。
当 CTE 在查询中仅被引用一次时,使用 CTE 对性能没有影响。
我建议处理查询,以便它可以在 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