0

我正在研究用于存储有关对象的无模式元数据的 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  |
+----------+------+------+
4

2 回答 2

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`
于 2012-11-15T14:38:13.963 回答
2

CASE使用和应用聚合函数GROUP BY。由于值是字符串,您可以使用 aMAX()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`

请参阅带有演示的 SQL Fiddle

如果您有未知数量的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;

请参阅带有演示的 SQL Fiddle

两者的结果将是:

|   ENTITY | BOB |   DEAN |
---------------------------
|  testEnt | foo | (null) |
| testEnt2 | foo |    foo |
于 2012-11-15T14:38:33.067 回答