如何解决SQLite:在使用 CASE 语句时如何避免使用两个 CTE?
我有一个具有以下架构的表 trx
:
| id | p_id |
| 1 | 1 |
| 2 | 1 |
| 3 | 4 |
...
| 1000 | 2 |
其中 id
是交易 ID,p_id
是执行者的 ID。
我需要查询 trx
所以我得到一个表格,它允许我绘制交易频率的直方图,这意味着,我想知道有多少 p_id
只做了 1 笔交易,有多少做了2,依此类推。我必须在 +10
箱中汇总 11 笔或更多交易:
| n_trx | bin_size |
| 1 | 10 |
| 2 | 18 |
| 3 | 7 |
...
| +10 | 26 |
我知道我需要 CASE
语句的 +10
语句,并且我使用两个 CTE
来完成任务:
WITH new_trx_history
AS (WITH trx_history
AS (SELECT p_id,Count(DISTINCT id) AS n_trx
FROM trx
GROUP BY p_id)
SELECT CASE
WHEN n_trx < 11 THEN n_trx
ELSE '+10'
END AS n_trx,Count(*) AS bin_size
FROM trx_history
GROUP BY n_trx)
SELECT n_trx,Sum(bin_size)
FROM new_trx_history
GROUP BY n_trx;
我想知道是否有比我实际的(工作)查询更直接的方法。
解决方法
您可以在 CASE
中使用 GROUP BY
WITH trx_history
AS (SELECT p_id,Count(DISTINCT id) AS n_trx
FROM trx
GROUP BY p_id)
SELECT CASE
WHEN n_trx < 11 THEN n_trx
ELSE '+10'
END AS n_trx,Count(*) AS bin_size
FROM trx_history
GROUP BY CASE
WHEN n_trx < 11 THEN n_trx
ELSE '+10'
END
;
,
如果使用 COUNT()
窗口函数,则无需任何 CTE 即可:
SELECT DISTINCT
CASE WHEN COUNT(*) >= 10 THEN '+10' ELSE COUNT(*) END AS n_trx,COUNT(*) OVER (PARTITION BY CASE WHEN COUNT(*) >= 10 THEN '+10' ELSE COUNT(*) END) AS bin_size
FROM trx
GROUP BY p_id
参见demo。
结果:
n_trx | bin_size
----- | --------
3 | 1
6 | 1
+10 | 3
,
我建议这样编写查询:
WITH p as (
SELECT p_id,Count(*) AS n_trx
FROM trx
GROUP BY p_id
)
SELECT (CASE WHEN n_trx < 11 THEN n_trx
ELSE '+10'
END) AS trx_grp,Count(*) AS bin_size
FROM p
GROUP BY trx_grp
ORDER BY MIN(n_trx);
注意事项:
- CTE 似乎不需要
COUNT(DISTINCT)
。id
在事务表中看起来是独一无二的,COUNT(DISTINCT)
会产生额外的开销。 - 您可以在 SQLite 中通过列别名进行聚合。但是,最好使用与
FROM
子句中的任何列不同的名称。 - 您可以使用聚合函数轻松订购。
- SQLite 允许您混合
CASE
表达式中的类型。这是由于它对类型的神秘处理。任何其他 SQL 方言都会将'+10'
转换为数字10
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。