如何将相同类型的值分组为共同的值和组

时间:2016-05-18 03:31:10

标签: mysql group-by

您好我正在寻找像enter image description here

这样的mysql查询结果

正如你所看到的,有一些值具有这种值(例如: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

先谢谢你们。

Otcome看起来像: enter image description here

2 个答案:

答案 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