如何使用 CASE 语句而不必将其放入 GROUP BY
Posted
技术标签:
【中文标题】如何使用 CASE 语句而不必将其放入 GROUP BY【英文标题】:How to use CASE statement without having to put it into GROUP BY 【发布时间】:2015-12-01 02:08:30 【问题描述】:我的查询有问题。这是我的代码:
select kpidate,reviewer as namareviewer,
count(formcode) as actual,
round((0.2*count(formcode))) as target,
CASE WHEN blibliknowledge !=''
THEN count(blibliknowledge)
END as blibli,
CASE WHEN solusi !=''
THEN count(solusi)
END as solusi
from kpi
where kpidate >= '30/11/2015' AND kpidate<= '1/12/2015'
group by reviewer,kpidate,blibliknowledge,solusi
由于CASE
表达式,我必须添加列blibliknowledge
和solusi
,输出将是这样的:
我想按namareviewer
分组,所以'elbert.lukman' 将被分组。所以输出只有两行。 blibli
和 solusi
列也将被计算为按 namareviewer 分组。
【问题讨论】:
是mysql还是postgresql相关的问题? @Shadow 我认为两者之间的查询语言是一样的。不是吗? @Shieryn:类似,但远不一样。 Postgres 更接近标准 SQL。 【参考方案1】:您似乎想要进行条件聚合。根据条件使用返回 1 或 0 的表达式,然后将其包装在 SUM 聚合中。或者,让表达式返回 NULL 和非 null 值,并将其包装在 COUNT 表达式中。
在 MySQL 中,日期文字应以 'yyyy-mm-dd'
格式提供。
举个例子:
SELECT k.kpidate
, k.reviewer AS namareviewer
, COUNT(k.formcode) AS actual
, ROUND((0.2*COUNT(k.formcode))) AS target
, SUM(CASE WHEN k.blibliknowledge != '' THEN 1 ELSE 0 END) AS blibli
, COUNT(CASE WHEN k.solusi != '' THEN 'foo' ELSE NULL END) AS solusi
FROM kpi k
WHERE k.kpidate >= '2015-11-30'
AND k.kpidate <= '2015-12-01'
GROUP
BY k.reviewer
, k.kpidate
在 MySQL 中,我们可以用布尔表达式简写 CASE
表达式。如果表达式计算结果为 TRUE,MySQL 返回整数值 1,如果表达式计算结果为 FALSE,则返回 0。如果表达式的计算结果为 NULL,则返回 NULL。
SELECT k.kpidate
, k.reviewer AS namareviewer
, COUNT(k.formcode) AS actual
, ROUND((0.2*COUNT(k.formcode))) AS target
, IFNULL(SUM(k.blibliknowledge != ''),0) AS blibli
, IFNULL(SUM(k.solusi != ''),0) AS solusi
FROM kpi k
WHERE k.kpidate >= '2015-11-30'
AND k.kpidate <= '2015-12-01'
GROUP
BY k.reviewer
, k.kpidate
【讨论】:
【参考方案2】:您也可以缩短 Postgres 中的语法。这适用于 Postgres 和 MySQL:
SELECT kpidate
, reviewer AS namareviewer
, count(formcode) AS actual
, round(count(formcode) * 0.2) AS target
, count(blibliknowledge <> '' OR NULL) AS blibli
, count(solusi <> '' OR NULL) AS solusi
FROM kpi
WHERE kpidate >= '2015-11-30'
AND kpidate < '2015-12-01' -- typically, you'd exclude that upper bound
GROUP BY reviewer, kpidate;
在 Postgres 9.4 中,您可以使用聚合 FILTER
子句的 SQL 标准实现:
SELECT kpidate
, reviewer AS namareviewer
, count(formcode) AS actual
, round(count(formcode) * 0.2) AS target
, count(*) FILTER (WHERE blibliknowledge <> '') AS blibli
, count(*) FILTER (WHERE solusi <> '') AS solusi
FROM kpi
WHERE kpidate >= '2015-11-30'
AND kpidate < '2015-12-01' -- typically, you'd exclude that upper bound
GROUP BY 1, 2; -- another optional syntax shortcut
还演示了一种语法简写,当您实际上必须在 SELECT
列表中引用一个较长的表达式时 - 也可以回答您的原始问题。
更多:
Conditional SQL count Concatenate multiple result rows of one column into one, group by another column【讨论】:
以上是关于如何使用 CASE 语句而不必将其放入 GROUP BY的主要内容,如果未能解决你的问题,请参考以下文章
我如何告诉 gcc 在 switch/case 语句上警告(或失败)而不中断?
如何使用 IF 或 Case 函数来汇总 GROUP_CONCAT 列?然后将其应用于原始数据表?
在带有 LIKE 的 CASE 语句中使用 GROUP_CONCAT 列别名