我有一个如下所示的mysql表,
id reasonCode
------ ------------------
1 0, 1
2 0
3 1, 2, 3
4 2
5 1, 0
我希望输出为
reasonCode occurrences
0 3
1 3
2 2
3 1
我试过" group by"但它给出了类似的东西。
reasonCode occurrences
0, 1 1
0 1
1, 2, 3 1
2 1
1, 0 1
如果有人知道该怎么做,将不胜感激。
答案 0 :(得分:1)
尝试此查询
SELECT Reason,COUNT(Reason) FROM
(
SELECT
id,
SUBSTRING_INDEX(SUBSTRING_INDEX(reasoncode, ',', n.digit+1), ',', -1) Reason
FROM
table1
INNER JOIN
(SELECT 0 digit UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) n
ON LENGTH(REPLACE(reasoncode, ',' , '')) <= LENGTH(reasoncode)-n.digit
ORDER BY
id,
n.digit
) T
Group By Reason;
<强> SQL FIDDLE 强>
输出将是:
REASON OCCURANCES
0 3
1 3
2 2
3 1
答案 1 :(得分:1)
...原因代码的数量将会改变。用户可以随时添加/删除原因代码......
如果原因代码的一部分未知,那么您最好生成查询动态。您可以通过存储过程执行此操作。
要遵循的步骤:
select
,其计数为1。Union all
如果生成了一些这样的陈述。示例代码段的一部分:
-- ...
set @sql_query := 'select reason_code, sum(rc_count) as rc_count from (' ;
set @sql_query :=
concat( @sql_query,
'\n ( select null as reason_code, 0 as rc_count )' );
-- ...
splitting_reason_codes: loop
set comma_position = locate( ',', reason_code_string );
if comma_position then
set rc := substring( reason_code_string, 1, comma_position-1 );
set reason_code_string :=
substring( reason_code_string, comma_position+1 );
else
set rc := reason_code_string;
end if;
if length( rc ) > 0 then
set @sql_query :=
concat( @sql_query,
'\n union all ( select ', rc, ', 1 )' );
end if;
if ! comma_position then
leave splitting_reason_codes;
end if;
end loop splitting_reason_codes;
-- ...
set @sql_query := concat( @sql_query, '\n) unique_reason_codes' );
set @sql_query := concat( @sql_query, '\nwhere reason_code is not null' );
set @sql_query := concat( @sql_query, '\ngroup by reason_code' );
set @sql_query := concat( @sql_query, '\norder by reason_code' );
prepare stmt from @sql_query;
execute stmt;
演示 @ SQL Fiddle
答案 2 :(得分:0)
如果你有一张原因代码表(我假设你这样做,所以你知道原因代码1的意思是什么),那么你可以这样做: -
SELECT a.id, COUNT(b.id)
FROM reason_codes a
LEFT OUTER JOIN id_reason_code b
ON FIND_IN_SET(a.id, b.reasonCode)
GROUP BY a.id
然而,一个问题是你的逗号后面有空格。逗号分隔字段在最好的时候是一个问题(最好分成另一个表的多行 - 如果需要的话,很容易将它们连接在一起),但逗号后面的空格会产生问题(注意删除这些空格)也会让@Vignesh Kumar的解决方案更简单一些。)
为了解决这个问题,你可以这样做: -
SELECT a.id, COUNT(b.id)
FROM reason_codes a
LEFT OUTER JOIN id_reason_code b
ON FIND_IN_SET(a.id, REPLACE(b.reasonCode, ' ', ''))
GROUP BY a.id
编辑 - 解释
这只是一个LEFT OUTER JOIN。这将占用第一个表中的每一行(即原因代码),并将其与第二个表上匹配的任何行匹配(即,ie_reason_code - 不确定您在上面显示的表格被调用);如果第二个表上没有匹配的行,那么第一个表中的行仍会被带回,但第二个表的列中为NULL。在这种情况下,连接基于FIND_IN_SET完成。这将查找逗号分隔值列表中的第一个参数,并在找到时返回位置(因此,如果发现它的计算结果为true)。
然后,COUNT / GROUP BY计算每个a.id的b.id值的数量并显示该数量。
第二个查询正在执行相同的操作,但它在检查值之前从逗号分隔列表中删除任何空格(当您有空格时需要以及将值分隔开的逗号)。
如果您有以下表格: -
reason_codes table
id reason
0 Reason A
1 Reason B
2 Reason C
3 Reason D
4 Reason E
id_reason_code table
id reasonCode
1 0,1
2 0
3 1,2,3
4 2
5 1,0
然后是以下sql(删除COUNT / GROUP BY): -
SELECT a.id, b.id
FROM reason_codes a
LEFT OUTER JOIN id_reason_code b
ON FIND_IN_SET(a.id, b.reasonCode)
将提供以下内容: -
a.id b.id
0 1
0 2
0 5
1 1
1 3
1 5
2 3
2 4
3 3
4 NULL
运行: -
SELECT a.id, COUNT(b.id)
FROM reason_codes a
LEFT OUTER JOIN id_reason_code b
ON FIND_IN_SET(a.id, b.reasonCode)
GROUP BY a.id
COUNT / GROUP BY为a.id的每个值赋予一行,然后为a.id的值为b.id的值(非null)计数: -
a.id count(b.id)
0 3
1 3
2 2
3 1
4 0
如果您愿意,也可以带回实际原因而不是代码: -
SELECT a.id, a.reason, COUNT(b.id)
FROM reason_codes a
LEFT OUTER JOIN id_reason_code b
ON FIND_IN_SET(a.id, b.reasonCode)
GROUP BY a.id, a.reason
,并提供: -
a.id a.reason count(b.id)
0 Reason A 3
1 Reason B 3
2 Reason C 2
3 Reason D 1
4 Reason E 0