lor*_*o-s 7 sql oracle group-by aggregate-functions
我正在尝试优化SQL查询以使我的报告看起来更好.我的查询从一个表读取数据,按几个列分组,并计算一些聚合字段(计数和总和).
SELECT A, B, C, COUNT(*), SUM(D) FROM T
GROUP BY A, B, C
ORDER BY A, B, C
Run Code Online (Sandbox Code Playgroud)
现在,我们假设B和C列是一些定义的常量字符串,例如,B可以是'B1'或'B2',C可以是'C1'或'C2'.因此,示例结果集是:
A | B | C | COUNT(*) | SUM(D)
--------------------------------
A1 | B1 | C1 | 34 | 1752
A1 | B1 | C2 | 4 | 183
A1 | B2 | C1 | 199 | 8926
A1 | B2 | C2 | 56 | 2511
A2 | B1 | C2 | 6 | 89
A2 | B2 | C2 | 12 | 231
A3 | B1 | C1 | 89 | 552
...
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,因为'A1'我有四种可能的(B,C)组合,但事实并非如此'A2'.我的问题是:如何在给定的表中生成(B,C)组合不存在的摘要行?也就是说,我如何打印,例如,这些行:
A | B | C | COUNT(*) | SUM(D)
--------------------------------
A2 | B1 | C1 | 0 | 0
A2 | B2 | C1 | 0 | 0
Run Code Online (Sandbox Code Playgroud)
我能看到的唯一解决方案是创建一些包含所有(B,C)值的辅助表,然后使用该aux表进行RIGHT OUTER JOIN.但我正在寻找一种更清洁的方式......
谢谢你们.
辅助表不必是真正的表,它可以是通用表表达式 - 至少如果您可以从表本身获取所有可能的值(或您感兴趣的所有值)。使用 @Bob Jarvis 的查询生成所有可能的组合,您可以执行以下操作:
WITH CTE AS (
SELECT * FROM (SELECT DISTINCT a FROM T)
JOIN (SELECT DISTINCT b, c FROM T) ON (1 = 1)
)
SELECT CTE.A, CTE.B, CTE.C,
SUM(CASE WHEN T.A IS NULL THEN 0 ELSE 1 END), NVL(SUM(T.D),0)
FROM CTE
LEFT JOIN T ON T.A = CTE.A AND T.B = CTE.B AND T.C = CTE.C
GROUP BY CTE.A, CTE.B, CTE.C
ORDER BY CTE.A, CTE.B, CTE.C;
Run Code Online (Sandbox Code Playgroud)
如果您有可能不在表中的固定值,那么它会更复杂一些(或者更丑陋,并且随着更多可能的值而变得更糟):
WITH CTE AS (
SELECT * FROM (SELECT DISTINCT a FROM T)
JOIN (SELECT 'B1' AS B FROM DUAL
UNION ALL SELECT 'B2' FROM DUAL) ON (1 = 1)
JOIN (SELECT 'C1' AS C FROM DUAL
UNION ALL SELECT 'C2' FROM DUAL) ON (1 = 1)
)
SELECT CTE.A, CTE.B, CTE.C,
SUM(CASE WHEN T.A IS NULL THEN 0 ELSE 1 END), NVL(SUM(T.D),0)
FROM CTE
LEFT JOIN T ON T.A = CTE.A AND T.B = CTE.B AND T.C = CTE.C
GROUP BY CTE.A, CTE.B, CTE.C
ORDER BY CTE.A, CTE.B, CTE.C;
Run Code Online (Sandbox Code Playgroud)
但你必须加入一些了解“缺失”值的事物。如果其他地方需要相同的逻辑,并且您有固定的值,那么永久表可能会更干净 - 当然,无论哪种方式都可能需要维护。您还可以考虑使用管道函数来充当代理表,但可能取决于卷。
| 归档时间: |
|
| 查看次数: |
287 次 |
| 最近记录: |