Mysql创建临时表并获取过滤后的数据

时间:2017-12-29 09:30:19

标签: php mysql mysqli

我有以下MySQL表(MySQL 5.6):

联系人

+----+----------------+
| id |     email      |
+----+----------------+
|  1 | one@domain.tld |
|  2 | two@domain.tld |
+----+----------------+

contact_attributes

+----+-------------+
| id |    name     |
+----+-------------+
|  1 | name        |
|  2 | current_car |
|  3 | car_color   |
+----+-------------+

contact_attribute_values

+----+------------+-------------------------+------------+
| id |   value    | contact_attribute_value | contact_id |
+----+------------+-------------------------+------------+
|  1 | John Doe   |                       1 |          1 |
|  2 | Eva Milton |                       1 |          2 |
|  3 | BMW X3     |                       2 |          1 |
|  4 | Volvo XC90 |                       2 |          2 |
|  5 | Pink       |                       3 |          1 |
|  6 | Blue       |                       3 |          2 |
+----+------------+-------------------------+------------+

有没有办法在MySQL中使用以下架构创建临时表来按属性获取和过滤联系人?

+------------+----------------+------------+-------------+-----------+
| contact_id | contact_email  |    name    | current_car | car_color |
+------------+----------------+------------+-------------+-----------+
|          1 | one@domain.tld | John Doe   | BMW X3      | Pink      |
|          2 | two@domain.tld | Eva Milton | Volvo XC90  | blue      |
+------------+----------------+------------+-------------+-----------+

感谢您的帮助

2 个答案:

答案 0 :(得分:3)

您可以创建一个生成此结果的视图:

CREATE VIEW contacts_view AS
SELECT
    c.id,
    c.email,     -- OK to select this since we GROUP BY the primary key
    MAX(CASE WHEN ca.name = 'name'        THEN cav.value END) AS name,
    MAX(CASE WHEN ca.name = 'current_car' THEN cav.value END) AS current_car,
    MAX(CASE WHEN ca.name = 'car_color'   THEN cav.value END) AS car_color
FROM contacts c
LEFT JOIN contact_attribute_values cav
    ON c.id = cav.contact_id
INNER JOIN contact_attributes ca
    ON cav.contact_attribute_value = ca.id
GROUP BY
    c.id;

SQLFiddle

可以创建一个临时表,其中包含上述视图的输出。但是我觉得一个观点更像是你在这之后所拥有的。会话结束后将删除临时表,这意味着您每次都必须再次填充。并且,一旦基础表中的数据发生变化,内部数据就会变得陈旧。

答案 1 :(得分:1)

使用CASE这样的表达式:

SELECT
  v.contact_id,
  MAX(CASE WHEN a.name = 'contact_email' THEN v.value ELSE '' END) AS 'contact_email',
  MAX(CASE WHEN a.name = 'name' THEN v.value ELSE '' END) AS 'name',
  MAX(CASE WHEN a.name = 'current_car' THEN v.value ELSE '' END) AS 'current_car'
  MAX(CASE WHEN a.name = 'car_color' THEN v.value ELSE '' END) AS 'car_color'
FROM contacts as c
INNER JOIN contact_attribute_values as v on c.id = v.contact_id
INNER JOIN contact_attributes as a on v.contact_attribute_value = a.id
group by v.contact_id;

你不必记下所有属性,你可以动态地制作它:

SET @cols = NULL;
SET @sql = NULL;

SELECT
  GROUP_CONCAT(DISTINCT CONCAT('MAX(IF(a.name = ''',
      a.name, ''', v.value , NULL)) AS ', '''', a.name , '''')
  ) INTO @cols
FROM contact_attributes a;


SET @sql = CONCAT('SELECT 
  v.contact_id,', @cols, '
    FROM contacts as c
LEFT JOIN contact_attribute_values as v on c.id = v.contact_id
INNER JOIN contact_attributes as a on v.contact_attribute_value = a.id
group by v.contact_id;');

prepare stmt 
FROM @sql;

execute stmt;