使用许多子查询优化查询

时间:2015-10-26 17:47:08

标签: sql sql-server subquery

我需要从两个表中查询数据,一个是父项(批处理),另一个是子项(详细信息),我在父项上过滤并希望根据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子句。

1 个答案:

答案 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作为包含的列。如果表格大量更新,这当然需要考虑。