-1

I have a relational DB that I can't think of how to form this query.

Here's the info

Table1

id name
1  Mike

Table2

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

Currently, this is my sql query

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

What this outputs is something like this

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

Is it possible to construct this in such a way to return these results so I can export it to a CSV file?

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

4

4 回答 4

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'
于 2013-01-13T19:27:43.960 回答
1

You need a conditional aggregation:

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
于 2013-01-13T19:26:08.733 回答
1

This type of data transformation is known an a pivot but MySQL does not have a pivot function. So you will want to replicate it using an aggregate function with a CASE expression.

If you know the the number of values ahead of time, then you can hard-code your query similar to this:

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;

See SQL Fiddle with Demo

But if you have an unknown number of values that you want to transform into columns, then you can use a prepared statement to generate dynamic sql.

The query would be similar to this:

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;

See SQL Fiddle with Demo

The result of both versions is:

| ID | NAME | SOMETHING | SOMETHING2 | SOMETHING3 |
---------------------------------------------------
|  1 | Mike |  setting1 |   setting2 |   setting3 |
于 2013-01-13T19:52:38.397 回答
0

GROUP_CONCAT may be of use. It doesn't give you exactly what you want, because it would put the concatenated values into a single field. But depending on what you're actually trying to accomplish, perhaps you can work around that. The advantage of the GROUP_CONCAT is that it can handle any number of table2 rows per table1 row, whereas the conditional aggregation above hardwires having three entries (which may well be what you want).

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

returns

id,person,value_group,setting_group
1,Mike,"something1,something2,something3","setting1,setting2,setting3"
于 2013-01-13T19:35:20.440 回答