質問

I have a problem and my SQL is too basic to get over it.
I have two tables:

TABLE1

  • id (int) - (primary key)
  • email (char)
  • other fields...

TABLE2

  • id (int) - (This is not the primary key nor is unique. This is a foreign key with respect to TABLE1.id)
  • key (char)
  • value (char)
  • other fields...

The second table has the structure "key-value".

For every TABLE1.id I have "many" rows in TABLE2 with TABLE1.id == TABLE2.id. In particular I can have the following situation:

A row in TABLE1

id = 10, email = "albert.einstein@genius.com", (other fields omitted)...

Corresponding rows in TABLE2

id = 10, key = "first_name", value = "Albert", (other fields omitted)...
id = 10, key = "last_name", value = "Einstein", (other fields omitted)...

I would like to write a SQL query which is able to return a table TABLE3 with the following structure:

TABLE3

  • id (int)
  • first_name (char)
  • last_name (char)
  • email (char)

The TABLE3 should contain a row for each row presents in TABLE1 and should be ordered by last_name and first_name

Following the example, I should obtain a table with rows similar to this one:

id = 10, first_name = "Albert", last_name = "Einstein", email = "albert.einstein@genius.com"

I'm getting crazy!!!

役に立ちましたか?

解決

You need to pivot these key value pairs into columns, unfortunately, MySQL doesn't have a pivot table operator. But you can use the CASE expression to do so:

SELECT
  t1.id,
  MAX(CASE WHEN t2.key = 'first_name' THEN value END) AS first_name,
  MAX(CASE WHEN t2.key = 'last_name' THEN value END) AS last_name,
  t1.email
FROM table1 AS t1 
INNER JOIN table2 AS t2 ON t1.id = t2.id
GROUP BY t1.id,
         t1.email;

SQL Fiddle Demo


If you want to do this dynamically and not to write all these values manually you have to use dynamic SQL to do this:

SET @sql = NULL;
SELECT
  GROUP_CONCAT(DISTINCT CONCAT('MAX(IF(t2.key = ''',
      t2.key, ''', t2.value, 0)) AS ', '''',   t2.key, '''')
  ) INTO @sql
FROM table2 AS t2;

SET @sql = CONCAT('
  SELECT
    t1.id,', @sql, ',
    t1.email
  FROM table1 AS t1 
  INNER JOIN table2 AS t2 ON t1.id = t2.id
  GROUP BY t1.id, t1.email');

prepare stmt 
FROM @sql;

execute stmt;

SQL Fiddle Demo

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top