如何将列数据作为行

时间:2014-08-12 12:26:54

标签: mysql crosstab

I have the following problem in MySQL 5.5. Here's my table.

Suppose i have a table With 'Names' with columns Rank,NAME and data in table 

When i run the query it will give result as 

select *from name 

    Rank | NAME  
    -------------
     1   |   A  
     1   |   B  
     1   |   C 
     2   |   D
     2   |   E  
     2   |   F 
     3   |   G  
     3   |   H 
     3   |   I  

现在,这当然是一种非常不方便的组织数据的方式,但这就是数据如何进入(并将继续进入)。

我需要能够使用与其各自等级相对应的NAMES列表,如下所示

    Rank  | Name    | Name  | Name
    -----------------------------------
      1   |   A     |  B    | C
      2   |   D     |  E    | F
      3   |   G     |  H    | I

我有像

这样的查询
select 
    case when rank=1 then name else null end as 1,
    case when rank=2 then name else null end as 2,
    case when rank=3 then name else null end as 3
    from name 

具有相同等级的名称需要被带到并显示在同一行。我不能估计学生将获得的最后一个等级,所以我不能通过使用' IN'手动传递等级值。运营商。由于排名值不可预测,我需要在交叉表视图中动态地将它们与其排名相对应。

我已尝试过各种动态交叉生成查询(是的,我已经看过所有这些查询),但我没有任何成功。请帮我。谢谢!

1 个答案:

答案 0 :(得分:2)

DROP TABLE IF EXISTS my_table;

 CREATE TABLE my_table
 (rank INT NOT NULL
 ,name CHAR(1) NOT NULL
 ,PRIMARY KEY(rank,name)
 );

 INSERT INTO my_table VALUES
 (1   ,'A'),
 (1   ,'B'),
 (1   ,'C'),
 (2   ,'D'),
 (2   ,'E'),
 (2   ,'F'),
 (3   ,'G'),
 (3   ,'H'),
 (3   ,'I');

 SELECT * FROM my_table;
 +------+------+
 | rank | name |
 +------+------+
 |    1 | A    |
 |    1 | B    |
 |    1 | C    |
 |    2 | D    |
 |    2 | E    |
 |    2 | F    |
 |    3 | G    |
 |    3 | H    |
 |    3 | I    |
 +------+------+

 SELECT x.*,COUNT(*) subrank FROM my_table x JOIN my_table y ON y.rank = x.rank AND y.name <= x.name GROUP BY x.rank,x.name;
 +------+------+---------+
 | rank | name | subrank |
 +------+------+---------+
 |    1 | A    |       1 |
 |    1 | B    |       2 |
 |    1 | C    |       3 |
 |    2 | D    |       1 |
 |    2 | E    |       2 |
 |    2 | F    |       3 |
 |    3 | G    |       1 |
 |    3 | H    |       2 |
 |    3 | I    |       3 |
 +------+------+---------+

 SELECT rank
      , MAX(CASE WHEN subrank = 1 THEN name END) name1
      , MAX(CASE WHEN subrank = 2 THEN name END) name2
      , MAX(CASE WHEN subrank = 3 THEN name END) name3
   FROM     
      ( SELECT x.*
             , COUNT(*) subrank 
          FROM my_table x 
          JOIN my_table y  
            ON y.rank = x.rank 
           AND y.name <= x.name 
         GROUP  
            BY x.rank
             , x.name
      ) a
  GROUP 
     BY rank;

 +------+-------+-------+-------+
 | rank | name1 | name2 | name3 |
 +------+-------+-------+-------+
 |    1 | A     | B     | C     |
 |    2 | D     | E     | F     |
 |    3 | G     | H     | I     |
 +------+-------+-------+-------+