【问题标题】:MySQL Transpose one column based on groupMySQL基于组转置一列
【发布时间】:2014-08-07 13:44:04
【问题描述】:

我有一张如下所示的表格:

Column1 Column2
1       A
1       B
1       C
2       D
2       A
2       B
2       E
2       F
3       A
3       D
3       C
3       H
3       J

MySQL中是否有查询显示如下信息:

Column1   Header1    Header2    Header3   Header4   Header5
1         A          B          C       
2         D          A          B         E         F
3         A          D          C         H         J

【问题讨论】:

  • 您尝试了什么,请向我们展示您遇到问题的代码,以便我们帮助您改进或增强它。
  • @Philip 公平地说,他们是在询问是否存在可以执行此操作的查询,而不是为查询提供帮助。
  • 您不能(合法地)按照您建议的方式对结果进行排序,因为您没有明确(在您的设计中)“2,D”在“2,A”之前的事实。 .. 为什么要将它们放在不同的列中?
  • @Strawberry 顺序并不特别重要。我只需要将它们显示在单独的列中,因为该表需要由其他用户(在 Excel 中)操作。 Arth 评论说,除非我可以按 As 然后 Bs 然后 Cs 排序数据,否则会更容易;但是我无法这样做,因为 column2 中的值变化很大。
  • 您确定行的值不会超过 5 个吗?

标签: mysql


【解决方案1】:

这是可能的...您必须通过使用 MAX() 和内部条件来模拟数据透视表。你只需要知道你想要多少列..

注意:

我只是调用了表格字母,因为从我的位置来看,这就是它的样子。

查询:

SELECT 
    id, 
    MAX(CASE counter WHEN 1 THEN letter ELSE ' ' END), 
    MAX(CASE counter WHEN 2 THEN letter ELSE ' ' END) ,
    MAX(CASE counter WHEN 3 THEN letter ELSE ' ' END) ,
    MAX(CASE counter WHEN 4 THEN letter ELSE ' ' END) ,
    MAX(CASE counter WHEN 5 THEN letter ELSE ' ' END) 
FROM
(   SELECT 
        id, letter, 
        IF(@A = id, @B := @B + 1, @B := 1) AS counter, 
        @A := id
    FROM letters
    CROSS JOIN(SELECT @A := 0, @B := 0) t
) temp
GROUP BY id;

所以对于这个查询,我为 id 设置了一个计数器.. 计算 id 的出现次数......所以你只需执行 MAX(CASE counter WHEN 1-5 THEN col2 ELSE ' ' END 表示当计数器为 1 - 5 时(如果你可能会更多有更多的 id) 输入对应的字母或空白.. 希望对您有帮助!

结果:

+----+------+-------+-------+-------+-------+
| ID | COL1 | COL2  | COL3  | COL4  | COL5  |
+----+------+-------+-------+-------+-------+
| 1  |  A   |   B   |   C   |               |
| 2  |  D   |   A   |   B   |   E   |   F   |
| 3  |  A   |   D   |   C   |   H   |   J   |
+----+------+-------+-------+-------+-------+

DEMO

【讨论】:

  • 嘿约翰,所以你的查询几乎成功了!但由于某种原因,它只返回与每个 ID 相关联的一些值,而不是所有值。为什么会这样?
  • @user3918629 没有看到你的数据我无法告诉你..尝试使用计数器的计算运行内部查询..看看它返回什么...确保计数器为每个递增重复 id 然后为下一个 id 重置为 1 .. 您可能需要先在子查询中按 id 排序结果.. 仅取决于发生的情况
  • 似乎计数器最多只能增加三个(这与我的问题一致),但在某些情况下还不止这些。我不明白为什么计数器会停在 3,但由于某种原因它是......
  • @user3918629 你的设置不正确,因为在我的示例中,计数器上升到 5,因为有 5 条重复记录。您需要发布确切的查询
  • 我没有更改您发送给我的查询的任何内容。但是,即使在有 5 条重复记录的情况下,查询也只返回 5 条中的 3 条。
【解决方案2】:

简单的答案是肯定的。

您要查找的基本查询是:

  SELECT column1, GROUP_CONCAT(column2 SEPARATOR ' ')
    FROM table_name
GROUP BY column1

您甚至可以对结果进行排序:

  SELECT column1, GROUP_CONCAT(column2 ORDER BY column2 SEPARATOR ' ')
    FROM table_name
GROUP BY column1
ORDER BY column1

【讨论】:

  • 它在 OPs 示例结果中没有排序,但如果没有合适的列,结果将是不可预测的,但您的第二个解决方案。
  • 对不起,这是我第一次发帖,所以我对格式不满意!我还需要将结果显示在各个列中。因此,对于第一行,条目“A”、“B”和“C”将分别位于其自己的列中。
  • @VMai,第二个解决方案通过 db 中 column2 的值对串联进行排序。或者这就是你的意思?
  • @user3918629 这不容易做到——尤其是没有合适的列来保证行的特定顺序。请将表格的行视为无序集。
  • @user3918629 来自右侧边栏的相关部分:stackoverflow.com/questions/9685601/… 请考虑在问题中提及此类要求。你可以给每一列一个标题。这将极大地帮助您的助手。
【解决方案3】:

或者,与 JR 的解决方案非常相似(并且略慢)...

  DROP TABLE IF EXISTS my_table;

  CREATE TABLE my_table
  (Column1 INT NOT NULL
  ,Column2 CHAR(1) NOT NULL
  ,PRIMARY KEY(Column1,Column2)
  );

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

  SELECT column1
       , MAX(CASE WHEN rank = 1 THEN column2 END) n1
       , MAX(CASE WHEN rank = 2 THEN column2 END) n2
       , MAX(CASE WHEN rank = 3 THEN column2 END) n3
       , MAX(CASE WHEN rank = 4 THEN column2 END) n4
       , MAX(CASE WHEN rank = 5 THEN column2 END) n5
    FROM
       ( SELECT x.*
              , COUNT(*) rank 
           FROM my_table x 
           JOIN my_table y 
             ON y.column1 = x.column1 
            AND y.column2 <= x.column2 
          GROUP 
             BY x.column1
              , x.column2
       ) n
   GROUP 
      BY column1;

  +---------+------+------+------+------+------+
  | column1 | n1   | n2   | n3   | n4   | n5   |
  +---------+------+------+------+------+------+
  |       1 | A    | B    | C    | NULL | NULL |
  |       2 | A    | B    | D    | E    | F    |
  |       3 | A    | C    | D    | H    | J    |
  +---------+------+------+------+------+------+

【讨论】:

  • 您可以在您的情况下添加一个ELSE ' ' 来模仿 OP 的预期结果:) 但这是按 id 排序结果的一个很好的解决方案
猜你喜欢
  • 1970-01-01
  • 2015-11-18
  • 1970-01-01
  • 2015-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多