简体   繁体   English

如何在 mysql 中动态地将 pivot 行列到列

[英]How to pivot rows to column dynamically in mysql

I'm facing a problem and I think I have to use pivot to solve it which I am not familiar with.我遇到了一个问题,我想我必须使用 pivot 来解决我不熟悉的问题。 I would be very thankful if someone would provide me help.如果有人能为我提供帮助,我将不胜感激。

The following query results in the following output.以下查询产生以下 output。 This is of course correct.这当然是正确的。

SELECT tm.team_id AS team, pp.user_name AS name, tm.rank AS rank
FROM teams_members AS tm 
    LEFT JOIN players_profiles AS pp
    ON pp.uid=tm.user_id
WHERE tm.team_id = 1 OR tm.team_id = 2
ORDER BY  tm.team_id, tm.rank
team团队 name姓名 rank
1 1 1Player1 1播放器1 1 1
1 1 1Player2 1玩家2 2 2
1 1 1Player3 1播放器3 2 2
1 1 1Player4 1播放器4 2 2
1 1 1Player5 1玩家5 3 3
1 1 1Player6 1玩家6 4 4
1 1 1Player7 1玩家7 5 5
2 2 2Player1 2播放器1 1 1
2 2 2Player2 2播放器2 2 2
2 2 2Player3 2播放器3 2 2
2 2 2Player4 2播放器4 2 2

I want the table to look like this though.我希望桌子看起来像这样。 How do I have to adapt the query?我如何调整查询? It is possible, that rank 2 can hold an unlimited amount of players.有可能,等级2可以容纳无限数量的玩家。 Rank 1,3,4 and 5 are set to a limit of 1.等级 1、3、4 和 5 设置为限制为 1。

team团队 1 1 2 2 2 2 2 2 3 3 4 4 5 5
1 1 1Player1 1播放器1 1Player2 1玩家2 1Player3 1播放器3 1Player4 1播放器4 1Player5 1玩家5 1Player6 1玩家6 1Player7 1玩家7
2 2 2Player1 2播放器1 2Player2 2播放器2 2Player3 2播放器3 2Player4 2播放器4
3 3 3Player1 3播放器1 3Player2 3播放器2 3Player3 3播放器3 3Player4 3播放器4 3Player5 3播放器5
4 4 4Player1 4播放器1 4Player2 4播放器2 4Player3 4播放器3 3Player4 3播放器4

I appreciate any help.我很感激任何帮助。 Thanks a lot!非常感谢!

To give you another example: DBFIDDLE再举一个例子: DBFIDDLE

DROP TABLE IF EXISTS testPivot ;
CREATE TABLE testPivot(i int, name varchar(20), k int);

INSERT INTO testPivot VALUES
   (1,'1Player1',1),
   (1,'1Player2',2),
   (1,'1Player3',2),
   (1,'1Player4',2),
   (1,'1Player5',3),
   (1,'1Player6',4),
   (1,'1Player7',5),
   (2,'2Player1',1),
   (2,'2Player2',2),
   (2,'2Player3',2),
   (2,'2Player4',2);
   
   
SELECT
  i as team,
  max(case when right(name,1)='1' then name else '' end) as '1',
  max(case when right(name,1)='2' then name else '' end) as '2',
  max(case when right(name,1)='3' then name else '' end) as '3',
  max(case when right(name,1)='4' then name else '' end) as '4',
  max(case when right(name,1)='5' then name else '' end) as '5',
  max(case when right(name,1)='6' then name else '' end) as '6',
  max(case when right(name,1)='7' then name else '' end) as '7'
FROM testPivot
GROUP BY i;

output: output:

team团队 1 1 2 2 3 3 4 4 5 5 6 6 7 7
1 1 1Player1 1播放器1 1Player2 1玩家2 1Player3 1播放器3 1Player4 1播放器4 1Player5 1玩家5 1Player6 1玩家6 1Player7 1玩家7
2 2 2Player1 2播放器1 2Player2 2播放器2 2Player3 2播放器3 2Player4 2播放器4

EDIT: The get group 2 in 1 column (I only applied the change for rank==2), use:编辑:在 1 列中获取第 2 组(我只应用了 rank==2 的更改),使用:

SELECT
  i as team,
  max(case when right(name,1)='1' then name else '' end) as '1',
  regexp_replace(regexp_replace(regexp_replace(group_concat(case when k=2 then name else '' end),'[,]+',','),'^,',''),',$','') as '2',
  -- max(case when right(name,1)='2' then name else '' end) as '2',
  max(case when right(name,1)='3' then name else '' end) as '3',
  max(case when right(name,1)='4' then name else '' end) as '4',
  max(case when right(name,1)='5' then name else '' end) as '5',
  max(case when right(name,1)='6' then name else '' end) as '6',
  max(case when right(name,1)='7' then name else '' end) as '7'
FROM testPivot
GROUP BY i;
team团队 1 1 2 2 3 3 4 4 5 5 6 6 7 7
1 1 1Player1 1播放器1 1Player2,1Player3,1Player4 1播放器2,1播放器3,1播放器4 1Player3 1播放器3 1Player4 1播放器4 1Player5 1玩家5 1Player6 1玩家6 1Player7 1玩家7
2 2 2Player1 2播放器1 2Player2,2Player3,2Player4 2播放器2,2播放器3,2播放器4 2Player3 2播放器3 2Player4 2播放器4

MySQL does not support PIVOT relational operator. MySQL 不支持 PIVOT 关系运算符。 But surely there is way to pivot data in MySQL.但肯定有办法在 MySQL 中获取 pivot 数据。 The challenge in your data was non uniqueness of pivot columns.您数据中的挑战是 pivot 列的非唯一性。 There would be multiple columns with name "2" in your output. output 中会有多个名称为“2”的列。

So I have created uniqueness by concatenating team last three later of name field.所以我通过连接名称字段的后三个团队来创建唯一性。 I am sharing here both static and dynamic pivoting for your data.我在这里分享 static 和数据的动态旋转。 In dynamic pivot it would not matter if you have three players or ten it will deliver your data in your required format.在动态 pivot 中,无论您有 3 个还是 10 个播放器,它都会以您所需的格式提供您的数据。 But if your team list is fixed along with player list then you can go for static pivot since it will be faster.但是,如果您的团队列表与玩家列表一起固定,那么您可以 go for static pivot 因为它会更快。

In dynamic pivot I have created your data as table t .在动态 pivot 中,我已将您的数据创建为表t You can put your entire select query in place of t .您可以将整个 select 查询代替t

Schema:架构:

 create table t (team   int, name   varchar(50) ,rank int);
 insert into t values(1,    '1Player1', 1);
 insert into t values(1,    '1Player2', 2);
 insert into t values(1,    '1Player3', 2);
 insert into t values(1,    '1Player4', 2);
 insert into t values(1,    '1Player5', 3);
 insert into t values(1,    '1Player6', 4);
 insert into t values(1,    '1Player7', 5);
 insert into t values(2,    '2Player1', 1);
 insert into t values(2,    '2Player2', 2);
 insert into t values(2,    '2Player3', 2);
 insert into t values(2,    '2Player4', 2);

Query#1 (static pivot)查询#1(静态枢轴)

   SELECT team, MAX(IF(concat(rank,right(name,3)) = '1er1', concat(rank,name), NULL)) AS "1",
    MAX(IF(concat(rank,right(name,3)) = '2er2', concat(rank,name), NULL)) AS "2",
    MAX(IF(concat(rank,right(name,3)) = '2er3', concat(rank,name), NULL)) AS "2",
    MAX(IF(concat(rank,right(name,3)) = '2er4', concat(rank,name), NULL)) AS "2",
    MAX(IF(concat(rank,right(name,3)) = '3er5', concat(rank,name), NULL)) AS "3",
    MAX(IF(concat(rank,right(name,3)) = '4er6', concat(rank,name), NULL)) AS "4",
    MAX(IF(concat(rank,right(name,3)) = '5er7', concat(rank,name), NULL)) AS "5" 
    FROM (SELECT tm.team_id AS team, pp.user_name AS name, tm.rank AS rank
FROM teams_members AS tm 
    LEFT JOIN players_profiles AS pp
    ON pp.uid=tm.user_id
WHERE tm.team_id = 1 OR tm.team_id = 2
ORDER BY  tm.team_id, tm.rank)t
    GROUP BY team

Query#2 (dynamic pivot)查询#2(动态枢轴)

 SET @sql = NULL;
 SELECT
   GROUP_CONCAT(DISTINCT
     CONCAT(
       'MAX(IF(concat(rank,right(name,3)) = ''',
       concat(rank,right(name,3)),
       ''', concat(rank,name), NULL)) AS ',
       concat('"',rank,'"')
     )
   ) INTO @sql
 FROM t;
 
 SET @sql = CONCAT('SELECT team
                     , ', @sql, ' 
                    FROM t
                    GROUP BY team');
 
 PREPARE stmt FROM @sql;
 EXECUTE stmt;
 DEALLOCATE PREPARE stmt;

Output: Output:

team团队 1 1 2 2 2 2 2 2 3 3 4 4 5 5
1 1 11Player1 11播放器1 21Player2 21播放器2 21Player3 21播放器3 21Player4 21播放器4 31Player5 31播放器5 41Player6 41播放器6 51Player7 51玩家7
2 2 12Player1 12播放器1 22Player2 22播放器2 22Player3 22播放器3 22Player4 22播放器4 null null null null null null

db<>fiddle here db<> 在这里摆弄

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM