使用" |"将列转换为行作为分隔符

时间:2014-07-11 14:25:56

标签: mysql sql max group-concat

请查看 Fiddle Example

我想将每个字段转换为此表中的一行:

CREATE TABLE product
    (`ID` int, `name` varchar(1), `category` varchar(11), `price` int,`year`int)
;

INSERT INTO product
    (`ID`, `name`, `category`, `price`,`year`)
VALUES
    (1, 'A', 'Outdoor', 25,2010),
    (2, 'A', 'Doll', 34,2009),
    (3, 'C', 'Doll', 25,2008),
    (4, 'D', 'Outdoor', 20,2010),
    (5, 'E', 'Brainteaser', 22,2010),
    (6, 'E', 'Brainteaser', 22,2009),
    (7, 'G', 'Brainteaser', 30,2009),
    (8, 'G', 'Brainteaser', 30,2009)
;

这是我想要获得的输出:

field           value
name            A,C,D,E,G
category        Brainteaser,Doll,Outdoor
price           20,22,25,30,34
year            2008,2009,2010

我阅读了一篇关于使用UNIONMAX转动表格的帖子,但我在MAX使用GROUP_CONCAT

时迷失了方向
   SELECT 
    MAX(CASE WHEN ... GROUP_CONCAT(DISTINCT (value) SEPARATOR '|')) as value
    from(
    select id,name value, 'name' field
    from product
    union all
    select id,category value, 'category' field 
    from product
    union all
    select id,price value, 'price' field
    from product
    union all
    select id,year value, 'year' field
    from product
      )
    GROUP BY field
    order by value

有谁能告诉我如何获得输出?

3 个答案:

答案 0 :(得分:3)

这将为您提供预期的输出:

SELECT 'name' AS `field`. GROUP_CONCAT(DISTINCT `name`  ORDER BY `name`) AS `value`
FROM product
UNION ALL
SELECT 'category' AS `field`. GROUP_CONCAT(DISTINCT `category` ORDER BY `category`) AS `value`
FROM product
UNION ALL
SELECT 'price' AS `field`. GROUP_CONCAT(DISTINCT `price` ORDER BY `price`) AS `value`
FROM product
UNION ALL
SELECT 'year' AS `field`. GROUP_CONCAT(DISTINCT `year` ORDER BY `year`) AS `value`
FROM product

添加ORDER BY因为看起来需要排序输出

答案 1 :(得分:2)

这样的事情?使用union all可以获得更好的性能,并且有任何重复。

SELECT 'name' field, group_concat(DISTINCT name ORDER BY name SEPARATOR '|') value FROM product
UNION ALL
SELECT 'category' field, group_concat(DISTINCT category ORDER BY category SEPARATOR '|') value FROM product
UNION ALL
SELECT 'price' field, group_concat(DISTINCT price ORDER BY price SEPARATOR '|') value FROM product
UNION ALL
SELECT 'year' field, group_concat(DISTINCT year ORDER BY year SEPARATOR '|') value FROM product;

修改 如果您只想通过一个查询来实现这一目标,就可以通过这种方式实现。

SELECT
    @uName := group_concat(DISTINCT name ORDER BY name SEPARATOR '|'),
    @uCat := group_concat(DISTINCT category ORDER BY category SEPARATOR '|') uCat,
    @uPrice := group_concat(DISTINCT price ORDER BY price SEPARATOR '|') uPrice,
    @uYear := group_concat(DISTINCT year ORDER BY year SEPARATOR '|') uYear
FROM product;

SELECT 'name' field, @uName value
UNION ALL
SELECT 'category' field, @uCat value
UNION ALL
SELECT 'price' field, @uPrice value
UNION ALL
SELECT 'year' field, @uYear value;

注意:您可以在ORDER BY

GROUP_CONCAT进行操作

答案 2 :(得分:1)

有一种方法可以完成您的请求,而无需使用许多查询查询您的表。实际上,下面的方法是将任何表转为pivot的方法。它将使用mysql prepared statements来准备SQL,然后执行它:

SELECT 
  GROUP_CONCAT(f SEPARATOR ' UNION ALL ') 
FROM 
  (SELECT 
    CONCAT(
      'SELECT "', 
      column_name,
      '" AS `field`, GROUP_CONCAT(DISTINCT ', 
      column_name,
      ') AS `value` FROM `', 
      @table_name, 
      '`'
    ) AS f 
    FROM 
      ((SELECT 
          column_name 
        FROM 
          INFORMATION_SCHEMA.COLUMNS 
        WHERE 
          table_name=@table_name && 
          table_schema=@schema_name
        ) AS fields 
        CROSS JOIN 
        (SELECT 
          @table_name := 'product', 
          @schema_name:= 'test'
        ) AS init)
      ) AS sqldata

上面的sql将产生一个字符串,可用于分配变量,如

mysql> SET @sql:=(SELECT GROUP_CONCAT(f SEPARATOR ' UNION ALL ') FROM (SELECT CONCAT('SELECT "', column_name,'" AS `field`, GROUP_CONCAT(DISTINCT ', column_name,') AS `value` FROM `', @table_name, '`') AS f FROM ((SELECT column_name FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name=@table_name && table_schema=@schema_name) AS fields CROSS JOIN (SELECT @table_name:='product', @schema_name:='test') AS init)) AS sqldata);
Query OK, 0 rows affected (0.03 sec)

接下来,准备:

mysql> PREPARE stmt FROM @sql;
Query OK, 0 rows affected (0.00 sec)
Statement prepared

最后,执行它:

mysql> EXECUTE stmt;
+----------+--------------------------+
| field    | value                    |
+----------+--------------------------+
| ID       | 1,2,3,4,5,6,7,8          |
| name     | A,C,D,E,G                |
| category | Outdoor,Doll,Brainteaser |
| price    | 25,34,20,22,30           |
| year     | 2010,2009,2008           |
+----------+--------------------------+
5 rows in set (0.00 sec)

好处是您独立于表结构,字段名称,e tc。这是一种通用方式 - 因此您可以使用它为任何桌子创建这样的枢轴。

关于变量@table_name@schema_name的几句话。它们指定了哪个表以及哪个模式将被转动。在上面的示例中,我使用CROSS JOIN将它们原地设置,但您可以单独设置它们,以便为枢轴维护不同的表。