查询和排序“键值”表

时间:2013-03-20 18:58:18

标签: mysql sql pivot entity-attribute-value

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

TABLE1

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

TABLE2

  • id(int) - (这不是主键,也不是唯一的。这是关于TABLE1.id的外键)
  • key(char)
  • value(char)
  • 其他领域......

第二个表的结构为“键值”。

对于TABLE1.id TABLE2 TABLE1.id == TABLE2.id中的每个id = 10, email = "albert.einstein@genius.com", (other fields omitted)... 我都有“很多”行。特别是我可以有以下情况:

TABLE1中的一行

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

TABLE2中的相应行

TABLE3

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

表3

  • id(int)
  • first_name(char)
  • last_name(char)
  • 电子邮件(char)

TABLE1应为last_name中显示的每一行包含一行,并且应按first_nameid = 10, first_name = "Albert", last_name = "Einstein", email = "albert.einstein@genius.com"

排序

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

{{1}}

我疯了!!!

1 个答案:

答案 0 :(得分: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 Fiddle Demo


如果要动态执行此操作而不是手动编写所有这些值,则必须使用动态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 Fiddle Demo