MySQL - 帮我构造这个查询

时间:2013-01-13 19:22:57

标签: mysql sql relational-database

我有一个关系数据库,我无法想到如何形成这个查询。

这是信息

表1

id name
1  Mike

表2

id table_1_id value      setting
1  1          something  setting1
2  1          something2  setting2
2  1          something3  setting3

目前,这是我的SQL查询

SELECT *  FROM Table1
JOIN Table2 on Table2.table_1_id = Table1.id

这输出的内容是这样的

id name table_1_id value      setting
1  Mike 1          something1 setting1
1  Mike 1          something2 setting2
1  Mike 1          something3 setting3

是否可以通过这种方式构建它以返回这些结果,以便将其导出为CSV文件?

id name table_1_id something1 something2 something3
1  Mike 1          setting1   setting2   setting3

4 个答案:

答案 0 :(得分:2)

SELECT
    Table1.*,
    something1Table.setting AS something1,
    something2Table.setting AS something2,
    something3Table.setting AS something3
FROM Table1
JOIN Table2 AS something1Table ON something1Table.table_1_id = Table1.id AND something1Table.value = 'something'
JOIN Table2 AS something2Table ON something2Table.table_1_id = Table1.id AND something2Table.value = 'something2'
JOIN Table2 AS something3Table ON something3Table.table_1_id = Table1.id AND something3Table.value = 'something3'

答案 1 :(得分:1)

您需要条件聚合:

select table1.id, table1.name,
       max(case when value = 'something1' then setting end) as setting1,
       max(case when value = 'something2' then setting end) as setting2,
       max(case when value = 'something3' then setting end) as setting3
from table1 join
     table2
     on table1.id = table2.id
group by table1.id, table1.name

答案 2 :(得分:1)

这种类型的数据转换称为 pivot ,但MySQL没有pivot功能。因此,您需要使用带有CASE表达式的聚合函数来复制它。

如果您提前了解了值的数量,那么您可以对查询进行硬编码,类似于:

select t1.id, 
  t1.name,
  max(case when t2.value = 'something' then t2.setting end) as setting1,
  max(case when t2.value = 'something2' then t2.setting end) as setting2,
  max(case when t2.value = 'something3' then t2.setting end) as setting3
from table1 t1
left join table2 t2
  on t1.id = t2.table_1_id
group by t1.id, t1.name;

请参阅SQL Fiddle with Demo

但是,如果您要将未知数量的值转换为列,则可以使用prepared statement to generate dynamic sql

查询与此类似:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT
    CONCAT(
      'max(case when t2.value = ''',
      value,
      ''' then t2.setting end) AS `',
      value, '`'
    )
  ) INTO @sql
FROM  table2;

SET @sql = CONCAT('SELECT t1.id, 
                    t1.name, ', @sql, ' 
                  FROM table1 t1
                  left join table2 t2
                    on t1.id = t2.table_1_id
                  group by t1.id, t1.name');

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

请参阅SQL Fiddle with Demo

两个版本的结果是:

| ID | NAME | SOMETHING | SOMETHING2 | SOMETHING3 |
---------------------------------------------------
|  1 | Mike |  setting1 |   setting2 |   setting3 |

答案 3 :(得分:0)

GROUP_CONCAT可能有用。它并不能完全满足您的需求,因为它会将连接的值放入单个字段中。但是,根据你实际想要完成的事情,也许你可以解决这个问题。 GROUP_CONCAT的优点是它可以处理每个table1行的任意数量的table2行,而上面的条件聚合有三个条目(这可能是你想要的)。

SELECT table1.*, 
    GROUP_CONCAT(value) AS value_group,
    GROUP_CONCAT(setting) AS setting_group 
FROM table1
INNER JOIN table2
ON table2.table_1_id = table1.id

返回

id,person,value_group,setting_group
1,Mike,"something1,something2,something3","setting1,setting2,setting3"