MySQL查询与组联系

时间:2013-11-19 00:12:29

标签: mysql sql group-concat mysql-select-db

假设我有一个名为“test”的表,其设计如下:

SELECT type, name, `key` FROM test
type | name    | key
------------------------
  0  | maria   | 123
  1  | gabriel | 455
  0  | rihanna | 69
  1  | chris   | 7
  1  | martin  | 112

下一个查询允许我将所有数据放在一行中:

SELECT GROUP_CONCAT(type ORDER BY type) types, GROUP_CONCAT(name ORDER BY type) names, GROUP_CONCAT(`key` ORDER BY type) `keys` FROM test
  types   |               names                |      keys
------------------------------------------------------------------
0,0,1,1,1 | rihanna,maria,martin,chris,gabriel | 69,123,112,7,455

但这并不是我所需要的。如果我能够创建一个返回以下结果的查询,那将是完美的:

types_0 |     names_0    |  keys_0  | types_1 |         names_1         |    keys_1
------------------------------------------------------------------------------------
  0, 0  | maria, rihanna |  123, 69 |   1, 1  | gabriel, chris, martin  | 455, 7, 112

有没有办法创建这样的查询?或者甚至没有意义呢?

提前谢谢。

2 个答案:

答案 0 :(得分:2)

有可能,但我不会这样做。它看起来像这样:

SELECT * FROM 
(
  SELECT 
    GROUP_CONCAT(type ORDER BY type) types, 
    GROUP_CONCAT(name ORDER BY type) names, 
    GROUP_CONCAT(`key` ORDER BY type) `keys` 
  FROM test
  WHERE type = 0
) AS _type0,
(
  SELECT 
    GROUP_CONCAT(type ORDER BY type) types, 
    GROUP_CONCAT(name ORDER BY type) names, 
    GROUP_CONCAT(`key` ORDER BY type) `keys` 
  FROM test
  WHERE type = 1
) AS _type1;

如果找到更多类型,则无法动态生成更多列。这是典型的数据透视表查询 - 在编写查询之前,您必须知道不同的值。

我会这样做:

SELECT 
  type,
  GROUP_CONCAT(name ORDER BY name) names, 
  GROUP_CONCAT(`key` ORDER BY name) `keys` 
FROM test
GROUP BY type;

输出应该如下:

 type |         names        |  keys
------------------------------------------------------------------
 0    | maria,rihanna        | 123,69
 1    | chris,gabriel,martin | 7,455,112

编辑:根据@ GarethD的回答,我在每个群组中按name进行了此查询排序。

答案 1 :(得分:2)

你可以这样做:

SELECT GROUP_CONCAT(CASE WHEN type = 0 THEN type END ORDER BY Type) AS types_0,
       GROUP_CONCAT(CASE WHEN type = 0 THEN name END ORDER BY Type) AS names_0,
       GROUP_CONCAT(CASE WHEN type = 0 THEN `key` END ORDER BY Type) AS keys_0,
       GROUP_CONCAT(CASE WHEN type = 1 THEN type END ORDER BY Type) AS types_1,
       GROUP_CONCAT(CASE WHEN type = 1 THEN name END ORDER BY Type) AS names_1,
       GROUP_CONCAT(CASE WHEN type = 1 THEN `key` END ORDER BY Type) AS keys_1
FROM   Test;

<强> Example on SQL Fiddle

或者,如果您不知道类型的数量,则可以动态生成SQL并使用预准备语句:

SET @SQL = '';

SELECT CONCAT('SELECT ',
                GROUP_CONCAT(DISTINCT
                    CONCAT('GROUP_CONCAT(CASE WHEN type = ', type, ' THEN type END ORDER BY Type) AS types_', type, ','
                            'GROUP_CONCAT(CASE WHEN type = ', type, ' THEN name END ORDER BY Type) AS names_', type, ','
                            'GROUP_CONCAT(CASE WHEN type = ', type, ' THEN `key` END ORDER BY Type) AS keys_', type
                    )), ' FROM Test;')
INTO    @SQL
FROM    Test;

PREPARE stmt FROM @SQL;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

<强> Example on SQL-Fiddle

,只是因为你可以做某事,并不意味着你应该这样做,而且我同意Bill Karwin,显示这些数据最明智的方法就是按类型分组。此外,您的查询不是确定性的,您应该通过不仅仅是键入的内容来订购,以确保名称和键的顺序是一致的。