拥有GROUP BY多个值可以为我提供所有可能的组合

时间:2014-09-30 07:22:43

标签: mysql sql group-by left-join cross-join

想象一下下表:

type cond
A    good
A    good
A    bad
B    good
B    bad
C    good
C    bad
D    good
D    bad
E    worse

如果我按typecond计算和分组,我会得到这个:

count type cond
2     A    good
1     A    bad
1     B    good
1     B    bad
1     C    good
1     C    bad
1     D    good
1     D    bad
1     E    worse

但是为了更好地将数据汇总到表格中,我更喜欢这样的结果:

count type cond
2     A    good
1     A    bad
0     A    worse
1     B    good
1     B    bad
0     B    worse
1     C    good
1     C    bad
0     C    worse
1     D    good
1     D    bad
0     D    worse
0     E    good
0     E    bad
1     E    worse

我已经设法将所有现有的type与所有现有的cond交叉加入,但我不能再计算了。 我还尝试将结果与所有现有的typecond联系起来,但这也不起作用。

SUM-CASE-WHEN策略在这里不起作用,因为我希望它具有动态性,即我不知道会有多少typecond

是否有简单(甚至复杂)的解决方案来生成分组数据的线性矩阵? (加分:......或者甚至将它转置,即2D矩阵,将一个组作为表头?)

3 个答案:

答案 0 :(得分:0)

试试这个:

SELECT 
  COUNT(c.type) as `count`, a.type, b.cond
FROM (
    SELECT DISTINCT type
    FROM table_name
  ) a
  CROSS JOIN (
    SELECT DISTINCT cond
    FROM table_name
  ) b
  LEFT JOIN
    table_name c ON c.type = a.type AND c.cond = b.cond
GROUP BY a.type, b.cond
ORDER BY a.type, b.cond

测试它:SQL Fiddle

修改

要在一个组作为表标题的2D矩阵中显示结果,您必须在运行查询之前知道组名。查询可以是:

SELECT 
  a.type,
  COUNT(CASE WHEN b.cond = 'good'  THEN c.type ELSE NULL END) as good,
  COUNT(CASE WHEN b.cond = 'bad'   THEN c.type ELSE NULL END) as bad,
  COUNT(CASE WHEN b.cond = 'worse' THEN c.type ELSE NULL END) as worse
FROM (
    SELECT DISTINCT type
    FROM table_name
  ) a
  CROSS JOIN (
    SELECT DISTINCT cond
    FROM table_name
  ) b
  LEFT JOIN
    table_name c ON c.type = a.type AND c.cond = b.cond
GROUP BY a.type
ORDER BY a.type

测试它:SQL Fiddle

答案 1 :(得分:0)

为了获得更好的数据结构,您必须拥有一张包含cond anagraph的表格,但是......

您可以使用两个子查询构建笛卡尔积,一个适用于所有类型,一个适用于所有类型,因此,您在SELECT字段上有一个子查询,您可以在其中计算这些元素的元素。

试试这个:

CREATE TABLE app(type char, cond varchar(10));

INSERT INTO app values
('A', 'good'),
('A', 'good'),
('A', 'bad'),
('B', 'good'),
('B', 'bad'),
('C', 'good'),
('C', 'bad'),
('D', 'good'),
('D', 'bad'),
('E', 'worse')

select t1.cond, t2.type, (select count(*) from app a3 where a3.cond = t1.cond 
and (a3.type = t2.type)) as total
from 
    (select distinct cond
    from app a1) as t1
cross join
    (select distinct type
    from app a2) as t2
order by t2.type, t1.cond

Show SqlFiddle

答案 2 :(得分:0)

select 
    A.type,
    A.cond,
    case
        when B.cnt is null then 0
        else B.cnt
    end
from
    (select 
        type, cond
    from
        (SELECT distinct
        cond
    from
        package)
    cross join (select distinct
        type
    from
        package)) A
        left join
    (select 
        type, cond, count(*) as cnt
    from
        package
    group by type , cond) B ON A.cond = B.cond and A.type = B.type
order by type