目前数据库如下所示:(具有名称值对的产品ID)
id,attribute_name,attribute_value
1,Clockspeed,1.6Ghz
1,屏幕,13.3"
2,Clockspeed,1.8Ghz
2,屏幕,15.1"
我想将上述数据转换为以下格式(由产品ID分隔,每个ID只有一行),以便迁移到新平台。
id,Clockspeed,Screen
1,1.6Ghz,13.3"
2,1.8Ghz,15.1"
实现这一结果的最简单方法是什么?我的直觉告诉我这将使用concat或group_concat函数来完成,但是我需要一个正确方向的点,因为拉出我的头发而秃顶。
答案 0 :(得分:2)
这指出了entity-attribute-value数据库设计的一个问题。
有两种方法可以使用SQL将属性转换为列,就好像您已将数据存储在传统表中一样:
SELECT id, MAX(CASE attribute_name WHEN 'Clockspeed' THEN attribute_value END) AS Clockspeed,
MAX(CASE attribute_name WHEN 'Screen' THEN attribute_value END) AS Screen
FROM eav_table
GROUP BY id;
SELECT id, c.attribute_value AS Clockspeed, s.attribute_value AS Screen
FROM eav_table AS c
JOIN eav_table AS s USING(id)
WHERE c.attribute_name = 'Clockspeed' AND s.attribute_name = 'Screen'
在MySQL 5.6上测试后输出两个查询:
+------+------------+--------+
| id | Clockspeed | Screen |
+------+------------+--------+
| 1 | 1.6GHz | 13.3" |
| 2 | 1.8GHz | 15.1" |
+------+------------+--------+
后一种解决方案需要N-1个连接才能输出N个属性。它不能很好地扩展。
上述两种解决方案都要求您根据要获取的属性数量编写相当多的应用程序代码来格式化SQL查询。这意味着如果属性数量不同(这可能是因为这是使用EAV的主要优势之一),那么可以为查询提取太多属性以获得良好的性能。
另一种解决方案是忘记仅使用SQL来转动数据。相反,每行向应用程序获取一行数据,因为它们存储在数据库中。然后编写应用程序代码以将结果后处理到一个对象中。