基于一列的组数据

时间:2012-09-26 12:35:37

标签: sql join group-by pivot

嗨我有数据库如下:

   id   | service | player |  name  |           value            
--------+---------+--------+--------+----------------------------
 104169 |    1232 | 313619 | age    | 30         
 104171 |    1232 | 313619 | email  | something@gmail.com
 104170 |    1232 | 313619 | gender | 0
 104172 |    1232 | 313620 | age    | 21
 104174 |    1232 | 313620 | email  | example@zoznam.sk
 104173 |    1232 | 313620 | gender | 1
 104175 |    1232 | 313621 | age    | 20
 104177 |    1232 | 313621 | email  | nothing@gmail.com
 104176 |    1232 | 313621 | gender | 1
 104178 |    1232 | 313622 | age    | 20
 104180 |    1232 | 313622 | email  | forth_mail@gmail.com
 104179 |    1232 | 313622 | gender | 1
 104181 |    1232 | 313625 | age    | 20
 104183 |    1232 | 313625 | email  | lastmail@citromail.hu
 104182 |    1232 | 313625 | gender | 1

我需要按播放器分组的输出如下:

 player |  age  |  gender | email            
--------+-------+---------+------------------
 313619 | 30    | 0       | something@gmail.com
 313620 | 21    | 1       | example@zoznam.sk
 313621 | 20    | 1       | nothing@gmail.com
 313622 | 20    | 1       | forth_mail@gmail.com
 313625 | 20    | 1       | lastmail@citromail.hu

任何想法?

3 个答案:

答案 0 :(得分:3)

试试这个:

   SELECT
     player,
     MAX(CASE WHEN name = 'email'   THEN  value END) AS email,
     MAX(CASE WHEN name = 'gender'  THEN value END) AS gender,
     MAX(CASE WHEN name = 'age' THEN value END) AS age
   FROM table 
   GROUP BY player

答案 1 :(得分:1)

你所拥有的是一团糟。我建议紧急重新考虑您的数据库设计。字段有数据类型是有原因的。

如果您的数据库支持PIVOT,您可以执行此操作...

select player, age,gender, email from 
(select player, name, value from yourtable) src
pivot 
(max(value) for name in ([age],[email],[gender])) p

答案 2 :(得分:0)

您没有指定RDBMS,但有几种方法可以执行此操作。如果您知道列数,则可以使用以下任一方法进行硬编码:

SELECT player,
     MAX(CASE WHEN name = 'email'   THEN  value END) AS email,
     MAX(CASE WHEN name = 'gender'  THEN value END) AS gender,
     MAX(CASE WHEN name = 'age' THEN value END) AS age
FROM yourtable 
GROUP BY player

MySQL Fiddle with Demo或者如果您的RDBMS具有PIVOT功能,那么:

select *
from 
(
  select player, name, value
  from yourtable
) x
pivot
(
  max(value)
  for name in ([age], [gender], [email])
) p;

SQL Server PIVOT Fiddle Demo

但是如果你在MySQL中有一个未知数量的列,你可以使用预准备语句:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'MAX(CASE WHEN name = ''',
      name,
      ''' then value else null end) AS ',
      name
    )
  ) INTO @sql
FROM Yourtable;

SET @sql = CONCAT('SELECT player, ', @sql, ' 
                  FROM yourtable 
                  GROUP BY player');

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

MySQL prepared statement Fiddle Demo或SQL-Server Dynamic SQL:

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(name) 
                    from yourtable
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT player, ' + @cols + ' from 
             (
                select player, name, value
                from yourtable
            ) x
            pivot 
            (
                max(value)
                for name in (' + @cols + ')
            ) p '

execute(@query)

SQL Server Dynamic Fiddle with Demo