3

我有一个问题,我的 SQL 太基础了,无法克服它。
我有两张桌子:

表格1

  • id (int) - (主键)
  • 电子邮件(字符)
  • 其他领域...

表2

  • id (int) - (这不是主键也不是唯一的。这是相对于 的外键TABLE1.id
  • 键(字符)
  • 值(字符)
  • 其他领域...

第二个表具有“键值”结构。

对于每一个我都有“TABLE1.id很多”行TABLE2TABLE1.id == TABLE2.id特别是我可以有以下情况:

TABLE1 中的一行

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

TABLE2 中的对应行

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

我想编写一个能够返回TABLE3具有以下结构的表的 SQL 查询:

表3

  • 标识(整数)
  • 名字(字符)
  • 姓氏(字符)
  • 电子邮件(字符)

TABLE3应该包含每一行出现的行,并且TABLE1应该由last_name和排序first_name

按照该示例,我应该获得一个包含与此类似的行的表:

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

我要疯了!!!

4

1 回答 1

3

您需要将这些键值对转换为列,不幸的是,MySQL 没有数据透视表运算符但是您可以使用CASE表达式来执行此操作:

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 小提琴演示


如果您想动态地执行此操作而不是手动编写所有这些值,则必须使用动态 SQL 来执行此操作:

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 小提琴演示

于 2013-03-20T19:03:29.040 回答