通过SQL数据进行多个分组

时间:2018-09-01 17:28:36

标签: php mysql sql

我在数据库中有一个类似的表:

id    desg        sr       per

1     desg-1      high     John Smith
2     desg-2      high     Peter Parker
3     desg-3      low      John Smith
4     desg-4      high     Mike
5     desg-5      high     Peter Parker
6     desg-6      low      John Smith   

现在我想用这种方式整理数据:

Name           count(desg)   high   low

John Smith     03            01     02
Peter Parker   02            00     02
Mike           01            01     00   

SQL语句应该是什么?可能是愚蠢的,但我真的无法理清结果。请帮帮我。

3 个答案:

答案 0 :(得分:1)

尽管mysql不支持pivot,但是您可以尝试使用条件聚合函数

CREATE TABLE T(
   ID INT,
   desg VARCHAR(50),
   sr VARCHAR(50),
   per VARCHAR(50)
);


INSERT INTO T VALUES (1,'desg-1','high','John Smith');
INSERT INTO T VALUES (2,'desg-2','high','Peter Parker');
INSERT INTO T VALUES (3,'desg-3','low','John Smith');
INSERT INTO T VALUES (4,'desg-4','high','Mike');
INSERT INTO T VALUES (5,'desg-5','high','Peter Parker');
INSERT INTO T VALUES (6,'desg-6','low','John Smith');

查询1

SELECT per,
    COUNT(desg),
    sum(CASE WHEN sr= 'high' THEN 1 else 0 END) high,
    sum(CASE WHEN sr= 'low' THEN 1 else 0  END) low
FROM T
GROUP BY per

Results

|          per | COUNT(desg) | high | low |
|--------------|-------------|------|-----|
|   John Smith |           3 |    1 |   2 |
|         Mike |           1 |    1 |   0 |
| Peter Parker |           2 |    2 |   0 |

如果要动态创建列,则可以使用动态数据透视。

create dynamic创建SQL并执行它。

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'sum(CASE WHEN sr= ''',
      sr,
      ''' THEN 1 else 0 END) ',
      sr
    )
  ) INTO @sql
FROM T;

SET @sql = CONCAT('SELECT per,
                     COUNT(desg), ', @sql, ' 
                   FROM T
                    GROUP BY per');

PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

sqlfiddle

答案 1 :(得分:0)

FWIW,就像您提到的应用程序代码(PHP)一样,我可能会做类似的事情,并处理表示层中的所有其他内容...

SELECT a.per
     , a.sr
     , SUM(COALESCE(b.sr = a.sr,0)) n
  FROM
     ( SELECT DISTINCT x.id, x.per, y.sr FROM my_table x, my_table y ) a
  LEFT
  JOIN my_table b
    ON b.id = a.id
   AND b.sr = a.sr
 GROUP
    BY per
     , sr
 ORDER
    BY per
     , sr;

答案 2 :(得分:0)

您似乎想要条件聚合。在MySQL中,使用sum()和布尔表达式很容易做到这一点:

select per, count(*) as num_desg,
       sum( sr = 'high' ) as num_high,
       sum( sr = 'low' ) as num_low
from t
group by per;

请注意,结果数字将不会有前导零。我认为那不是可取的。如果确实需要,可以将数字转换为左侧填充的字符串。