2012-08-26 80 views
0

我有一個名爲Properties(pid,uid,pname,pvalue)的表。 pid列是自動生成的。每個uid(用戶標識)可以有多個存儲在pname和pvalue中的名稱值對。Where子句中有多個名稱/值對的SQL查詢

作爲輸入,我爲pname和pvalue創建了多個名稱值對,它們構成了一個複雜的布爾表達式。

例如:讓我們開始帶有一個名稱值對。假設我想要檢索所有'favorite_color'爲'紅色'的uid。

我寫了一個SQL查詢:

SELECT * 
    FROM properties 
WHERE ((pname = 'favorite_color') and (pvalue = 'red')) 

查詢,如果我不得不檢索類似,獲取所有的UID,其「favorite_color」是「紅色」或「藍色」和「favorite_drink」很快變得複雜是「果汁」或「奶」和‘favorite_愛好’是‘音樂’或‘藝術’等

我寫了一個SQL查詢:

SELECT * 
    FROM properties 
WHERE (((pname = 'favorite_color') and (pvalue = 'red')) 
    OR ((pname = 'favorite_color') and (pvalue = 'blue'))) 
    AND (((pname = 'favorite_drink') and (pvalue = 'juice')) 
    OR ((pname = 'favorite_drink') and (pvalue = 'milk'))) 
    AND (((pname = 'favorite_hobby') and (pvalue = 'music')) 
    OR ((pname = 'favorite_hobby') and (pvalue = 'art'))) 

我表達正確但不幸的是它失敗,因爲評估是在每一行完成的。如果我想爲where子句添加更多名稱值對,該怎麼辦?

問題:

  1. 是否可以寫,爲此SQL查詢?

  2. 我的另一個想法是獲取每個用戶的所有pname,pvalue對,使用表達式語言和我的輸入名稱值巴黎來構建一個動態表達式來評估它。我在考慮apache的JEXL。

+1

使用'UNION' /'UNION ALL'(根據需要)分開標準 –

+0

您是否在暗示這樣的事情? SELECT * FROM properties WHERE(((pname ='favorite_color')和(pvalue ='red')) OR((pname ='favorite_color')和(pvalue ='blue')))UNION SELECT * FROM ((pname ='favorite_drink')和(pvalue ='juice')) OR ='favorite_hobby')和(pvalue ='music')) OR((pname ='favorite_hobby')和(pvalue ='art'))) – user977505

+0

是的,這是正確的 –

回答

2

做你需要做的儘可能多的與運算自聯接,你有和ED條件:

SELECT * 
FROM Properties p1, Properties p2, Properties p3 
WHERE p1.uid = p2.uid AND p1.uid = p3.uid 
AND (p1.pname = 'favorite_color' AND p1.pvalue IN ('red', 'blue')) 
AND (p2.pname = 'favorite_drink' AND p2.pvalue IN ('juice', 'milk')) 
AND (p3.pname = 'favorite_hobby' AND p2.pvalue IN ('music', 'art')) 

編輯:

另一種可能性是進行非規範化的數據,然後用FIND_IN_SET()RLIKE

SELECT uid, group_concat(concat(pname, '=', pvalue)) props 
FROM Properties 
GROUP BY uid 
HAVING props RLIKE 'favorite_color=(red|blue)' 
AND props RLIKE 'favorite_drink=(juice|milk)' 
AND props RLIKE 'favorite_hobby=(music|art)' 
+0

它是有道理的,但現在我有6個這樣的屬性(favorite_ *),它可以增長得更多。其中6個笛卡爾積(例如表中的1M行)會導致什麼結果?我甚至無法想象這種複雜性。我應該考慮重構我的模式/表格嗎? – user977505

+0

在編輯中查看我的新查詢。 – Barmar

+0

它看起來不錯。這正是我想要作爲我的問題的一部分實現的目標(#2點)。獲取使用SQL查詢作爲前半部分的uid屬性對,並在構成下半部分的java代碼中處理它們。沒有意識到SQL本身對函數有着固有的豐富支持。我會試試更多一點,並更新你。我再次感謝幫助。 – user977505

0
SELECT p1.*,p2.pname,p2.pvalue,p3.pname,p3.pvalue 
FROM (
     (Select * 
     from Properties 
     where (pname = 'favorite_color' AND pvalue IN ('red', 'blue')) p1, 
     (Select * 
     from Properties 
     where (pname = 'favorite_drink' AND pvalue IN ('juice','milk')) p2, 
     (Select * 
     from Properties 
     where (pname = 'favorite_hobby' AND pvalue IN ('music', 'art')) p3, 
    ) 
WHERE p1.uid = p2.uid AND p1.uid = p3.uid 
+0

這聽起來不錯,但我解決這個問題的唯一問題是可擴展性。我添加查詢的屬性越多,結果就越複雜。 – user977505