在MySQL中选择动态列

7

能否遍历这样的表:

mysql> select * from `stackoverflow`.`Results`;
+--------------+---------+-------------+--------+
| ID           | TYPE    | CRITERIA_ID | RESULT |
+--------------+---------+-------------+--------+
|            1 | car     | env         | 1      |
|            2 | car     | gas         |        |
|            3 | car     | age         |        |
|            4 | bike    | env         | 1      |
|            5 | bike    | gas         |        |
|            6 | bike    | age         | 1      |
|            7 | bus     | env         | 1      |
|            8 | bus     | gas         | 1      |
|            9 | bus     | age         | 1      |
+--------------+---------+-------------+--------+
9 rows in set (0.00 sec)

转换成如下形式:

+------+-----+-----+-----+
| TYPE | env | gas | age |
+------+-----+-----+-----+
| car  | 1   |     |     |
| bike | 1   |     | 1   |
| bus  | 1   | 1   | 1   |
+------+-----+-----+-----+

目的是选择所有的CRITERIA_ID并将其用作列。而我想使用所有TYPE作为行。

  • 所有的Criterias: SELECT distinct(CRITERIA_ID) FROM stackoverflow.Results;
  • 所有的Types: SELECT distinct(TYPE) FROM stackoverflow.Results;

但是如何将它们结合成视图或类似于此的东西?

如果您想玩弄数据,这是一个生成表的脚本:

CREATE SCHEMA `stackoverflow`;
CREATE TABLE `stackoverflow`.`Results` (
  `ID` bigint(20) NOT NULL AUTO_INCREMENT,
  `TYPE` varchar(50) NOT NULL,
  `CRITERIA_ID` varchar(5) NOT NULL,
  `RESULT` bit(1) NOT NULL,
  PRIMARY KEY (`ID`)
) 
ENGINE=InnoDB;

INSERT INTO `stackoverflow`.`Results`
(
 `ID`,
 `TYPE`,
 `CRITERIA_ID`,
 `RESULT`
)
VALUES
( 1, "car", env, true ),
( 2, "car", gas, false ),
( 3, "car", age, false ),
( 4, "bike", env, true ),
( 5, "bike", gas, false ),
( 6, "bike", age, true ),
( 7, "bus", env, true ),
( 8, "bus", gas, true ),
( 9, "bus", age, true );

1个回答

13

很遗憾,MySQL没有一个名为PIVOT的函数,这基本上是你想要做的事情。所以你需要使用带有CASE语句的聚合函数:

SELECT type,
  sum(case when criteria_id = 'env' then result end) env,
  sum(case when criteria_id = 'gas' then result end) gas,
  sum(case when criteria_id = 'age' then result end) age
FROM results
group by type

请参考以下文章,如果您想要动态执行此操作,也就是说您事先不知道转置的列,请阅读以下文章:Dynamic pivot tables (transform rows to columns)

您的代码应该类似于下面这样:

查看带有演示的SQL Fiddle

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'SUM(IF(CRITERIA_ID = ''',
      CRITERIA_ID,
      ''', RESULT, NULL)) AS ',
      CRITERIA_ID
    )
  ) INTO @sql
FROM
  Results;
SET @sql = CONCAT('SELECT type, ', @sql, ' FROM Results GROUP BY type');

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

请查看带演示的SQL Fiddle


+1 实现预处理语句。动态 SQL 可能被低估了。但需要注意的是:不能在函数或触发器中使用。 - georgepsarakis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接