我需要从两个表中查询数据,一个是父项(批处理),另一个是子项(详细信息),我在父项上过滤并希望根据where子句返回父项的所有项,但是有选择地将子表的不同方面过滤为父结果集的摘要列。
话虽如此,这是我现在的查询有效:(对不起,我删除了一些无关紧要但又想保留子查询的东西)
SELECT
workid,
siteid,
(
SELECT
top 1 description
FROM
worksrcdesc a
WHERE
a.workid = b.workid
AND
a.site = b.site
ORDER BY
date DESC
) AS descript,
itemid,
mode,
systemdate,
(
SELECT
count(sequence)
FROM
details a
WHERE
a.reject = 0
AND
a.itemid = b.itemid
AND
a.siteid = b.siteid
AND
documenttype IN (1,2)
) AS documentcount,
(
SELECT
count(sequence)
FROM
details a
WHERE
a.reject = 0
AND
a.itemid = b.itemid
AND
a.siteid = b.siteid
AND
documenttype = 15
) AS othercount,
(
SELECT
count(distinct tranno)
FROM
details a
WHERE
a.reject = 0
AND
a.itemid = b.itemid
AND
a.siteid = b.siteid
) AS transactioncount,
(
SELECT
top 1 groupnum
FROM
groups d
WHERE
b.siteid = d.siteid
AND
b.workid = d.workid
) AS sitegrouping
FROM
batches b with (nolock)
WHERE
workid IN (12345,67980)
ORDER BY
workid ASC,
itemid ASC
批处理表有54,000行,按工作ID限制过滤到300个条目。详细信息表有330万行,根据批次使用的相同标准将其过滤到大约76,000行。
现在这需要4-5秒才能平均运行;有没有办法简化这个以使其运行更快?我想过做连接而不是子查询,但是什么抛弃了我(我无法让它工作)是子查询中不同的where子句。
答案 0 :(得分:1)
至少你可以将你的子查询组合成一个外部应用:
outer apply (
SELECT
sum(case when documenttype IN (1,2) then 1 else 0 end) as documentcount,
sum(case when documenttype = 15 then 1 else 0 end) as othercount,
count(distinct tranno) as transactioncount
FROM
details a
WHERE
a.reject = 0 AND
a.itemid = b.itemid AND
a.siteid = b.siteid
)
如果sequence可以为null,则可能需要在sum子句中检查它。
索引也很重要,特别是如果匹配的行数很高,那么时间不会花在键查找上。您很可能希望将indexid与itemid,siteid和reject + documenttype以及tranno作为包含的列。如果表格大量更新,这当然需要考虑。