2012-11-29 32 views
1

在SQLite中,我想編寫一個SELECT查詢來查找具有某些屬性+值或不具有某些屬性的文章,其中屬性位於另一個表中。SQL查詢,查找具有一些屬性和丟失其他屬性的文章

這是我是如何組織我有一個數據庫:

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"; 

但如果我想找到顏色爲黃色的文章,但是沒有任何長度特徵。即我想要橡皮鴨,因爲它沒有長度,但我不想要水管。

在我的UI,可以選擇:

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

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

我的文章表具有20K〜行,並設有20萬〜。

也許我的數據庫不適合這種查詢?如有必要,我可以輕鬆地重新生成它。

回答

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進行檢查。

+0

謝謝,你把我推向了正確的方向。這個計劃應該和你的替代方案#3一樣。 – johv