当前数据库如下所示:(带有名称值对的产品 ID)
id、属性名称、属性值
1、主频1.6Ghz
1、屏幕,13.3 英寸
2、主频,1.8Ghz
2、屏幕,15.1"
我想将上述数据转换为以下格式(以产品ID分隔,每个ID仅一行),以便迁移到新平台。
id、时钟速度、屏幕
1、1.6Ghz、13.3"
2、1.8Ghz、15.1"
实现这一结果的最简单方法是什么?我的直觉告诉我,这将通过 concat 或 group_concat 函数来完成,但我需要一个正确方向的点,因为我的头发会被拔掉而秃头。
最佳答案
这指出了 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 来转换数据。相反,将数据库行提取到应用程序,每行一个属性,因为它们存储在数据库中。然后编写应用程序代码以将结果后处理到一个对象中。
关于MySQL 需要帮助将垂直数据格式化为水平数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23744952/