在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。
也许我的数据库不适合这种查询?如有必要,我可以轻松地重新生成它。
答案 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进行检查。