我正在开发一个EAV存储系统,用于存储有关对象的无模式元数据,现在正在开发一种可搜索的方法,但大部分处理都是由数据库服务器完成的。
EAV表是:
`entityID` - INT(11)
`entity` - VARCHAR(128)
`attribute` - VARCHAR(128)
`value` - BLOB
这是我的陈述:
SELECT
`entity`,
(CASE WHEN `attribute` = 'bob' THEN `value` ELSE NULL END) `bob`,
(CASE WHEN `attribute` = 'dean' THEN `value` ELSE NULL END) `dean`
FROM `eav`
返回一组很好的行(如预期的那样),如下所示:
+----------+------+------+
| entity | bob | dean |
+----------+------+------+
| testEnt | foo | NULL | // attribute = bob
+----------+------+------+
| testEnt | NULL | NULL | // another test attribute
+----------+------+------+
| testEnt | NULL | NULL | // another test attribute
+----------+------+------+
| testEnt2 | foo | NULL | // attribute = bob
+----------+------+------+
| testEnt2 | NULL | foo | // attribute = dean
+----------+------+------+
但是当我附上GROUP BY (Entity)
时,结果变为:
+----------+------+------+
| entity | bob | dean |
+----------+------+------+
| testEnt | foo | NULL |
+----------+------+------+
| testEnt2 | foo | NULL |
+----------+------+------+
所以在此之后使用HAVING
语法停止工作。有没有办法让返回的结果是:
+----------+------+------+
| entity | bob | dean |
+----------+------+------+
| testEnt | foo | NULL |
+----------+------+------+
| testEnt2 | foo | foo |
+----------+------+------+
答案 0 :(得分:3)
唯一的问题是您的记录已GROUP
,但您尚未汇总字段。通过使用MAX
聚合字段来尝试。
SELECT
`entity`,
MAX(CASE WHEN `attribute` = 'bob' THEN `value` ELSE NULL END) `bob`,
MAX(CASE WHEN `attribute` = 'dean' THEN `value` ELSE NULL END) `dean`
FROM `eav`
GROUP BY `entity`
答案 1 :(得分:2)
使用CASE
和GROUP BY
应用聚合函数。由于值是字符串,因此您可以使用MAX()
或MIN()
来返回结果:
SELECT
`entity`,
Max(CASE WHEN `attribute` = 'bob' THEN `value` ELSE NULL END) `bob`,
Max(CASE WHEN `attribute` = 'dean' THEN `value` ELSE NULL END) `dean`
FROM `eav`
group by `entity`
如果您要返回未知数量的attribute
值,则可以使用预准备语句来获取结果:
SET @sql = NULL;
SELECT
GROUP_CONCAT(DISTINCT
CONCAT(
'max(case when attribute = ''',
attribute,
''' then value end) AS ',
attribute
)
) INTO @sql
FROM eav;
SET @sql = CONCAT('SELECT entity, ', @sql, '
FROM eav
GROUP BY entity');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
两者的结果将是:
| ENTITY | BOB | DEAN |
---------------------------
| testEnt | foo | (null) |
| testEnt2 | foo | foo |