SQL查询查找具有某些属性且缺少其他属性的文章

时间:2012-11-29 18:01:24

标签: sqlite select filter key-value entity-attribute-value

在SQLite中,我想写一个SELECT查询来查找具有某些属性+值的文章,或者没有某些属性的文章,其中属性在另一个表中。

这就是我组织我所拥有的数据库的方式:

Articles:

ID  Name
1   Paper clip
2   Water hose
3   Rubber duck

Features
ID    Articles_ID  Name    Value
1     1            Color   White
2     2            Color   Yellow
3     2            Length  1.4m
4     3            Color   Yellow

如果我想找到颜色为黄色的文章,我可以这样做:

SELECT distinct a.Name from Articles a join Features f
             where a.ID = f.Articles_ID
               and f.Name = "Color"
               and f.Value = "Yellow";

但是,如果我想找到颜色为黄色的文章,但没有任何长度功能,该怎么办?即我想要橡皮鸭,因为它没有长度,但我不想要水管。

在我的用户界面中,可以选择:

Color: [ ] <empty>
       [x] Yellow
       [ ] White
       [ ] ...

Length: [x] <empty>
        [ ] 0.7m
        [ ] 1.4m
        [ ] ...

我的文章表有~20k行,功能约200k。

也许我的数据库不适合这种查询?如有必要,我可以轻松地重新生成它。

1 个答案:

答案 0 :(得分:1)

(注意:您可能需要文章ID,在这种情况下您不需要DISTINCT;并且联接的语法应为tableA JOIN tableB ON condition。)

有三种可能性:你可以获得所有黄色文章,然后exclude所有文章都有长度:

SELECT a.ID,
       a.Name
FROM Articles a
JOIN Features f ON a.ID = f.Articles_ID
WHERE f.Name = 'Color'
  AND f.Value = 'Yellow'
EXCEPT
SELECT a.ID,
       a.Name
FROM Articles a
JOIN Features f ON a.ID = f.Articles_ID
WHERE f.Name = 'Length'

或者,使用子查询来匹配不存在相应Length记录的记录:

SELECT a.ID,
       a.Name
FROM Articles a
JOIN Features f ON a.ID = f.Articles_ID
WHERE f.Name = 'Color'
  AND f.Value = 'Yellow'
  AND NOT EXISTS (SELECT ID
                  FROM Features f2
                  WHERE f2.Articles_ID = a.ID
                    AND f2.Name = 'Length')

或者,使用LEFT JOIN加入所有Length功能,并匹配此类联接未成功的记录。 (在第一个要素连接中使用Color条件时,此查询是最常规的。)

SELECT a.ID,
       a.Name
FROM Articles a
JOIN      Features f1 ON  a.ID = f1.Articles_ID
                      AND f1.Name = 'Color'
LEFT JOIN Features f2 ON  a.ID = f2.Articles_ID
                      AND f2.Name = 'Length'
WHERE f1.Value = 'Yellow'
  AND f2.Value IS NULL

哪种查询最有效取决于您拥有的索引以及SQLite是否决定使用它们。 使用EXPLAIN QUERY PLAN进行检查。