如您所见,有些值具有这种值(例如:BV 和 BR 或 C5 和 C7)我如何将它们组合成一个共同的值让我们说 B 或 C 并在 sql 中按它们分组? 我有以下查询:
SELECT
type,
sum(case when status ='valid' then 1 else 0 end) valid_jobs,
sum(case when status ='non-valid' then 1 else 0 end) non_valid_jobs,
sum(case when status IS NULL then 1 else 0 end) null_jobs
from
main_table
where
SUBSTRING_INDEX(CAST(CAST(from_unixtime(date_generated) AS DATE) AS CHAR), '-',2) REGEXP '^2016'
group by type
提前谢谢你们。
最佳答案
只需使用一个表达式来评估 type
列的值,并返回所需的结果。
问题中不清楚的是从 type
到您希望在第一列中返回的值的“映射”。看起来我们可能只查看 type
列中值的第一个字符。
SUBSTR(type,1,1)
如果“映射”涉及更多,那么我们可以使用 CASE 表达式。例如:
CASE
WHEN type IN ('BV','BR','BT','ZB') THEN 'B'
WHEN type IN ('C5','C7') THEN 'C'
WHEN ... THEN ...
ELSE type
END
我们会将其用作 SELECT 列表中的第一个表达式(替换原始查询中对 type
列的引用),以及 GROUP BY 子句中的第一个表达式。
在(不相关的)性能说明中,我们希望 WHERE 子句中的条件位于裸列。这允许 MySQL 在适当的索引上使用(高效的)范围扫描操作。
有了这个条件:
WHERE SUBSTRING_INDEX(CAST(CAST(FROM_UNIXTIME( t.date_generated ) AS DATE) AS CHAR), '-',2)
REGEXP '^2016'
我们强制 MySQL 为表中的每一行 计算左侧的表达式。比较表达式返回的值。
如果我们真正想做的是获取 2016 年的 date_generated
值,假设 date_generated
是 INTEGER 类型,存储 32 位 unix 风格的秒数自 1970-01-01 时代开始...
我们可以这样做:
WHERE t.date_generated >= UNIX_TIMESTAMP('2016-01-01')
AND t.date_generated < UNIX_TIMESTAMP('2017-01-01')
MySQL 会将其视为对 date_generated
列中值的范围操作。这样,MySQL 就可以有效地利用以 date_generated
作为前导列的索引。
只需将 expr
替换为在第一列中返回您想要的值的表达式:
SELECT expr
, SUM(IF( t.status = 'valid' ,1,0)) AS valid_jobs
, SUM(IF( t.status = 'non-valid' ,1,0)) AS non_valid_jobs
, SUM(IF( t.status IS NULL ,1,0)) AS null_jobs
FROM main_table t
WHERE t.date_generated >= UNIX_TIMESTAMP('2016-01-01')
AND t.date_generated < UNIX_TIMESTAMP('2017-01-01')
GROUP BY expr
编辑
要保证以特定顺序返回行,请添加 ORDER BY 子句,例如
ORDER BY 1
关于mysql - 如何将相同类型的值分组为共同值并按该值分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37289784/