【问题标题】:MySQL query with group contact带有组联系人的 MySQL 查询
【发布时间】:2013-11-19 00:12:28
【问题描述】:

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

SELECT type, name, `key` FROM test
类型 |姓名 |钥匙 ---------------------- 0 |玛丽亚 | 123 1 |加布里埃尔 | 455 0 |蕾哈娜 | 69 1 |克里斯 | 7 1 |马丁 | 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
类型 |姓名 |钥匙 -------------------------------------------------- ---------------- 0,0,1,1,1 |蕾哈娜、玛丽亚、马丁、克里斯、加布里埃尔| 高分辨率照片| CLIPARTO 69,123,112,7,455

 

但这并不是我所需要的。如果我能够创建一个返回以下结果的查询,那就太完美了: 类型_0 |姓名_0 |键_0 |类型_1 |姓名_1 |键_1 -------------------------------------------------- ---------------------------------- 0, 0 |玛丽亚,蕾哈娜 | 123, 69 | 1, 1 |加布里埃尔、克里斯、马丁| 高分辨率照片| CLIPARTO 455、7、112

 

有没有办法创建这样的查询?还是根本没有意义?

提前致谢。

【问题讨论】:

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


    【解决方案1】:

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

    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 进行了此查询。

    【讨论】:

    • 感谢您的帮助。
    【解决方案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 的观点,显示这些数据的最明智的方式是按类型分组。此外,您的查询不是确定性的,您应该按不仅仅是键入的内容进行排序,以确保名称和键的顺序是一致的。

    【讨论】:

    • +1 是的,我同意应该按type 以外的其他内容进行排序,根据定义,每个组内按类型划分。我将编辑我的答案以表明这一点。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多