【问题标题】:mysql transform fields to columnmysql将字段转换为列
【发布时间】:2016-11-03 22:46:54
【问题描述】:

我有以下表格

表 1 表 2 id q_id 内容 id w_id q_id c_id 排名 ---------------------- ---------------------------- -------------------- 95 2046 1=E 123 22404 2046 100 1 96 2046 2=G 124 22404 2046 101 2 97 2046 3=N 125 22404 2046 102 2 98 2046 4=B 126 22404 2046 103 2 99 2046 5=V 127 22404 2046 104 3 100 2046 A1 128 22404 2046 105 3 101 2046 A2 102 2046 A3 103 2046 A4 104 2046 A5 105 2046 A6

我需要从表格行转换到列

原始结果:

c_id 内容 E G N B V ---------------------------------------------- 100 A1 1 0 0 0 0 101 A2 0 1 0 0 0 102 A3 0 1 0 0 0 103 A4 0 1 0 0 0 104 A5 0 0 1 0 0 105 A6 0 0 1 0 0

结果一的代码:

(SELECT c.id, c.content, a.E, a.G, a.N, a.B, a.V FROM table_1 t
INNER JOIN 
(SELECT t1.id,  
  Count(IF(t2.ranking=1,1,0)) AS E,
  Count(IF(t2.ranking=2,1,0)) AS G,
  Count(IF(t2.ranking=3,1,0)) AS N,
  Count(IF(t2.ranking=4,1,0))AS B,
  Count(IF(t2.ranking=5,1,0)) AS V
FROM table_1 t1, table_2 t2 
WHERE t1.question_id = 2046 AND t2.question_id = 2046 AND t2.choice_id = t1.id 
AND t2.ranking >= 0 AND t2.w_id IN (22404)
GROUP BY t1.id) a ON a.id = t1.id);

到新结果:

内容 A1 A2 A3 A4 A5 A6 ----------------------------------------------------------- 1=E 1 0 0 0 0 0 2=G 0 1 1 1 0 0 3=N 0 0 0 0 1 1 4=B 0 0 0 0 0 0 5=V 0 0 0 0 0 0

我正在使用 MySql,但无法使用 pivot。另外,我想我不会知道否。表 1 中的“A”表示最高可达“A30”。因此它应该是动态的...... 谁能给我关于结果 2 的建议?


@bluefeet 我想我需要在 where caluse 中再添加两个条件,因为左连接可能会加入 table_1 中的大量数据。所以它不能显示结果。

select c.content,
sum(case when t1.content = 'A1' then 1 else 0 end) A1,
sum(case when t1.content = 'A2' then 1 else 0 end) A2,
sum(case when t1.content = 'A3' then 1 else 0 end) A3,
sum(case when t1.content = 'A4' then 1 else 0 end) A4,
sum(case when t1.content = 'A5' then 1 else 0 end) A5
from table_1 c
left join table_2 t2
on left(c.content, 1) = t2.ranking
left join table_1 t1
on t2.c_id = t1.id
where locate('=', c.content) > 0 and c.id IN (95,96,97,98,99) and w_id = 22404
group by  c.content;

结果会是这样的

| CONTENT | A1 | A2 | A3 | A4 | A5 | A6 |
-----------------------------------------
|     1=E |  1 |  0 |  0 |  0 |  0 |  0 |
|     2=G |  0 |  1 |  1 |  1 |  0 |  0 |
|     3=N |  0 |  0 |  0 |  0 |  1 |  1 |

缺少两行(4=B,5=V)。

我该如何解决?

【问题讨论】:

  • 你是否只有5个排名?
  • yes 5 排名只有结果 2 中的列不同
  • @bluefeet 你能帮帮我吗?

标签: mysql pivot


【解决方案1】:

下面的查询应该会给你结果,但是它做了一些假设:

  • 最后的content 列将始终有一个等号=。这用于定位内容中的行。
  • 带有= 符号的content 列值将关联的排名作为第一个字符。此字符用于将行加入table_2 中的排名

如果您有已知数量的值,则可以使用以下内容:

select c.content,
  sum(case when t1.content = 'A1' then 1 else 0 end) A1,
  sum(case when t1.content = 'A2' then 1 else 0 end) A2,
  sum(case when t1.content = 'A3' then 1 else 0 end) A3,
  sum(case when t1.content = 'A4' then 1 else 0 end) A4,
  sum(case when t1.content = 'A5' then 1 else 0 end) A5
from table_1 c
left join table_2 t2
  on left(c.content, 1) = t2.ranking
left join table_1 t1
  on t2.c_id = t1.id
where locate('=', c.content) > 0
group by  c.content;

SQL Fiddle with Demo

如果您要拥有未知数量的A 值,那么您可以使用准备好的语句来生成动态 SQL:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'sum(CASE WHEN t1.content = ''',
      content,
      ''' THEN 1 else 0 END) AS `',
      content, '`'
    )
  ) INTO @sql
FROM Table_1
where locate('=', content)= 0;

SET @sql 
  = CONCAT('SELECT c.content, ', @sql, ' 
            from table_1 c
            left join table_2 t2
              on left(c.content, 1) = t2.ranking
            left join table_1 t1
              on t2.c_id = t1.id
            where locate(''='', c.content) > 0
            group by  c.content;');

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

SQL Fiddle with Demo。两者都给出了结果:

| CONTENT | A1 | A2 | A3 | A4 | A5 | A6 |
-----------------------------------------
|     1=E |  1 |  0 |  0 |  0 |  0 |  0 |
|     2=G |  0 |  1 |  1 |  1 |  0 |  0 |
|     3=N |  0 |  0 |  0 |  0 |  1 |  1 |
|     4=B |  0 |  0 |  0 |  0 |  0 |  0 |
|     5=V |  0 |  0 |  0 |  0 |  0 |  0 |

【讨论】:

  • @user2210819 不客气,这是一个有趣的问题! :)
  • 动态的正在php中测试?
  • @user2210819 看这个demo,你会把w_id过滤器放在JOIN上——sqlfiddle.com/#!2/393c0/99
  • 终于可以解决问题了。你依靠我的救命稻草!非常感谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-13
  • 1970-01-01
  • 2021-08-14
相关资源
最近更新 更多