正如你所看到的,有一些值具有这种值(例如: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
先谢谢你们。
答案 0 :(得分:2)
只需使用一个表达式来计算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会将其视为te 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
答案 1 :(得分:1)
试试这个,
SELECT
LEFT(type,1) AS 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