SQL 优化:使用不同的 where 子句查询 table

SQL Optimization: query table with different where clauses

我有以下 SQL 查询:

SELECT (
    SELECT SUM(c1)
    FROM t2
    WHERE t1.c1 = t2.c1
    AND t2.c3 = 'NEW'
    AND t2.c4 = TRUNC(SYSDATE)
    AND t2.c5 = 'N'
) SUM,
(
    SELECT sum(c2)
    FROM t2
    WHERE t1.c1 = t2.c1
    AND t2.c3 = 'OLD'
    AND t2.c4 = TRUNC(SYSDATE)
) SUM2
FROM t1
WHERE t1.c2 IN ('DUMMY', 'DUMMY2')

因此,t2 table 被多次查询,但每次都有不同的 WHERE 子句。这个 t2 table 非常大,所以需要一些时间才能得到结果。最好只使用所有不同的 WHERE 子句和 SUM 结果查询此 table 一次..

这有可能吗?我得到了在 SQL 中使用 WITH AS 的建议,但我的执行时间没有成功

你可以试试这个:

SELECT SUM1.val, SUM2.val
FROM (SELECT * FROM t1 WHERE t1.c2 IN ('DUMMY', 'DUMMY2')) as t1
INNER JOIN (
    SELECT SUM(c1) as val
    FROM t2
    WHERE t2.c3 = 'NEW'
        AND t2.c4 = TRUNC(SYSDATE)
        AND t2.c5 = 'N'
) SUM1
    ON t1.c1 = SUM1.c1
INNER JOIN (
    SELECT SUM(c2) as val
    FROM t2
    WHERE t2.c3 = 'OLD'
        AND t2.c4 = TRUNC(SYSDATE)
) SUM2
    ON t1.c1 = SUM2.c1

您可以对 t2 中的 case 表达式进行多次 sum 调用,然后将其加入 t1:

SELECT sum1, sum2
FROM   t1
JOIN   (SELECT c1, 
               SUM(CASE WHEN c3 = 'NEW' AND 
                             c4 = TRUNC(SYSDATE) AND 
                             c5 = 'N' THEN c1 
                        ELSE NULL END) AS sum1,
               SUM(CASE WHEN c3 = 'OLD' AND 
                             c4 = TRUNC(SYSDATE) THEN c2 
                        ELSE NULL END) AS sum2
        FROM   t2) t2 ON t1.c1 = t2.c1
WHERE  t1.c2 IN ('DUMMY', 'DUMMY2')

编辑:case 表达式(即 c4 = TRUNC(SYSDATE))中的常见条件可以提取到 where 子句,这应该会提供一些性能增益:

SELECT sum1, sum2
FROM   t1
JOIN   (SELECT c1, 
               SUM(CASE WHEN c3 = 'NEW' AND c5 = 'N' THEN c1 
                        ELSE NULL END) AS sum1,
               SUM(CASE WHEN c3 = 'OLD' THEN c2 
                        ELSE NULL END) AS sum2
        FROM   t2
        WHERE  c4 = TRUNC(SYSDATE)) t2 ON t1.c1 = t2.c1
WHERE  t1.c2 IN ('DUMMY', 'DUMMY2')

这个查询给了我与你原来的 SQL 相同的结果,样本数据:

with 
  a as (select c1 from t1 where c2 in ('DUMMY', 'DUMMY2')),
  b as (
    select c1,
        sum (case when c3 = 'NEW' and c5 = 'N' then c1 end) sum1,
        sum (case when c3 = 'OLD' then c2 end) sum2
      from t2 
      where c4 = trunc(sysdate) and exists (select 1 from a where c1 = t2.c1)
      group by c1
    )
select * from a left join b using (c1)

SQLFiddle

...而且应该更快,因为我试图将它限制在必要的步骤内。 如果列 c1 在 table t1 中是唯一的,那么查询可能会被简化,但我在这里没有假设唯一性。

顺便说一句 - 您确定 sum1 是对 c1 列求和,而不是 c2