可以在T-SQL查询中重用标准吗?

时间:2014-01-30 14:21:25

标签: sql tsql

我的SQL查询看起来像这样:

SELECT
    o.name,
    o.type_id, 
    (SELECT COUNT(*) FROM a WHERE type_id = o.type_id AND id IN ('1, 2, 3 ... 1000')) AS count_a, 
    (SELECT COUNT(*) FROM b WHERE type_id = o.type_id AND id IN ('1, 2, 3 ... 1000')) AS count_b, 
    (SELECT COUNT(*) FROM c WHERE type_id = o.type_id AND id IN ('1, 2, 3 ... 1000')) AS count_c
FROM o

在子查询(count_a,count_b和count_c)中,IN子句中指定的条件对于每个条件都是相同的,但它是一个非常长的数字列表(实际上不是顺序的),并且我担心:

a)我把查询放慢了太长时间了 b)它会变得太长并最终导致错误

有没有办法别名/引用该标准列表(可能作为变量?),以便可以在查询中出现的三个位置中的每个位置重复使用它?或者我什么都不担心?

更新

鉴于使用CTE的建议,我已将上面的查询改为现在这样工作:

WITH id_list AS (SELECT id FROM source WHERE id IN ('1, 2, 3 ... 1000'))
SELECT
    o.name,
    o.type_id, 
    (SELECT COUNT(*) FROM a WHERE type_id = o.type_id AND id IN (SELECT id FROM id_list)) AS count_a, 
    (SELECT COUNT(*) FROM b WHERE type_id = o.type_id AND id IN (SELECT id FROM id_list)) AS count_b, 
    (SELECT COUNT(*) FROM c WHERE type_id = o.type_id AND id IN (SELECT id FROM id_list)) AS count_c
FROM o

这会将查询的总长度减少到原来的三分之一,虽然数据库似乎需要花费几毫秒才能执行查询,但至少我不会遇到基于长度的错误查询太长了。

问题:有没有一种快速方法可以将逗号分隔的数字列表(1,2,3 ... 1000)分解为可用作CTE的结果集?

2 个答案:

答案 0 :(得分:3)

您可以使用common-table-expression(CTE):

WITH Numbers AS
(
    SELECT N 
    FROM (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 1000)
    AS T(N)
)
SELECT
    o.name,
    o.type_id, 
    (SELECT COUNT(*) FROM a WHERE type_id = o.type_id AND id IN (SELECT N FROM Numbers)) AS count_a, 
    (SELECT COUNT(*) FROM b WHERE type_id = o.type_id AND id IN (SELECT N FROM Numbers)) AS count_b, 
    (SELECT COUNT(*) FROM c WHERE type_id = o.type_id AND id IN (SELECT N FROM Numbers)) AS count_c
FROM o 

答案 1 :(得分:0)

如果你的id是其他表中的外键,那么你可以从列表中创建一个表变量,然后重复加入。

DECLARE @id_list TABLE (
  id INT
)

INSERT INTO @id_list
SELECT id
FROM pk_location
WHERE id IN ('1, 2, 3 ... 1000')

SELECT
    o.name,
    o.type_id, 
    (SELECT COUNT(*) FROM a INNER JOIN @id_list i ON a.id = i.id WHERE type_id = o.type_id) AS count_a, 
    (SELECT COUNT(*) FROM b INNER JOIN @id_list i ON b.id = i.id WHERE type_id = o.type_id) AS count_b, 
    (SELECT COUNT(*) FROM c INNER JOIN @id_list i ON c.id = i.id WHERE type_id = o.type_id) AS count_c
FROM o