2013-05-13 65 views
1

我有兩個表:如何針對表連接上的多個條件進行匹配?

users   attributes 
id|name  id|name|user_id 
-------  --------------- 
1 |foo   1 |bla | 1 
2 |bar   1 |blub| 1 
       1 |bla | 2 

如何創建一個查詢,使用戶無論是「喇嘛」和「咕嚕咕嚕」的屬性?

在這種情況下,它應該只返回用戶「foo」。

我知道數據沒有正常化。

+0

我做的編輯到你的問題和標題,希望它會更清晰。如果您覺得我沒有改善您的問題,請隨時恢復。 – Jeff 2013-05-13 17:21:19

回答

4
SELECT u.*, a.id, b.Id, a.name, b.name FROM users u 
JOIN attributes a 
ON a.User_id = u.User_id AND a.name = 'bla' 
JOIN attributes b 
ON u.User_Id = b.User_id AND b.name = 'blub' 
+1

我覺得'u.name'應該是'a.name'和'b.name'。 – 2013-05-13 17:06:46

+0

@LinusCaldwell:你完全正確,修正。 – Jeff 2013-05-13 17:07:52

+1

我會把這個值包裹起來,例如:''bla''。但是,正確答案爲+1。 – 2013-05-13 17:08:41

0
SELECT u.name 
FROM attributes a 
JOIN users u 
    ON u.id = a.user_id 
WHERE a.name IN ('bla','bulb') 
+2

這將永遠不會工作 - a.name不能同時'bla'和'bulb',你正在對不同字符串的同一個字段進行非通配符匹配。 – Jeff 2013-05-13 17:09:42

+0

哇,很好的電話。 – wilsjd 2013-05-13 17:14:21

+0

目前的修訂版恐怕沒有太多變化。 ;-) – 2013-05-13 17:15:07

2

假設一個屬性關聯到用戶是唯一的......

,如果你需要3個條件是真實的條件添加到在調整計數1

SELECT u.name 
FROM users u 
INNER JOIN attributes a on A.user_Id = u.id 
WHERE a.name in ('bla','blub') 
GROUP by u.name 
HAVING count(*)=2 

如果你沒有一個獨特的關聯,或者你需要加入到另一張桌子,你可以隨時做...

SELECT u.name 
FROM users u 
INNER JOIN attributes a on A.user_Id = u.id 
WHERE a.name in ('bla','blub') 
GROUP by u.name 
HAVING count(distinct A.name)=2 

輕微的表現打擊。但是這可以讓你加入並獲得其他領域,其他人已經表明這是對這種方法的損害。

這允許縮放解決方案,而不是承擔每次加入不同表的費用。另外,如果您需要三十個值進行關聯,您可能會遇到允許的連接數限制。

+0

這個工作,我想,但如果他需要超過users.name或users.user_id作爲輸出它不會工作非常好。 – Jeff 2013-05-13 17:17:59

+0

@Jeff查看更新。有很多方法來剝皮這隻貓。 – xQbert 2013-05-13 20:13:22

1
SELECT U.NAME 
FROM USERS U 
INNER JOIN 
     ATTRIBUTES A1 
ON  U.ID = A1.USER_ID 
INNER JOIN 
     ATTRIBUTES A2 
ON  U.ID = A2.USER_ID 
WHERE A1.NAME = 'bla' 
AND  A2.NAME = 'blub' 
+0

這是有效的,但是我發現當你把條件放在'on'語句上時,它似乎變得更快 - 我相信當你這樣做時,它可能在連接之前修剪表。無論我是否正確,對我而言似乎更快(儘管我沒有任何東西,只有主觀分析來支持)。 – Jeff 2013-05-13 17:13:13

+0

@Jeff,我同意。當我運行這些類型的查詢時,我總是使用'JOIN'子句的這一部分。我是這樣寫的,因爲我贊成易於理解性能。 – 2013-05-13 17:14:57

+0

對@ Declan而言,值得注意的是,從可維護性的角度來看,將它保留在WHERE子句中是可取的。 – wilsjd 2013-05-13 17:18:17

1

可以使用INTERSECT操作

SELECT 
    u.id 
    ,u.name 
    FROM users AS u 
    INNER JOIN attributes AS a 
    ON u.id = a.user_id 
    WHERE a.name = 'bla' 

INTERSECT 

SELECT 
    u.id 
    ,u.name 
    FROM users AS u 
    INNER JOIN attributes AS a 
    ON u.id = a.user_id 
    WHERE a.name = 'blub' 
; 

這裏是SQL小提琴演示:http://sqlfiddle.com/#!6/68986/5

更多在SQL中設置操作信息:http://en.wikipedia.org/wiki/Set_operations_(SQL)

+0

我沒有使用INTERSECT(或任何SET操作),但它看起來好像它的工作。任何熟悉套件的人都可以閱讀。性能與多重連接方法相比如何? – Jeff 2013-05-13 17:23:28

+0

這取決於很多不同的因素。這裏是一篇關於性能的博客文章:http://sqlserverpedia.com/blog/sql-server-bloggers/t-sql-set-operators-intersect-except-and-union/ 我會建議比較執行計劃。 – 2013-05-13 17:43:41

相關問題