2011-11-07 22 views
0

我有三個表:如何使這一JOIN工作

CREATE TABLE credential_types (
    id serial PRIMARY KEY, 
    name varchar(32) NOT NULL, 
    ... 
); 

CREATE TABLE credentials (
    user_id integer REFERENCES users(id), 
    credential integer REFERENCES credential_types(id), 
    UNIQUE (user_id, credential) 
); 

CREATE TABLE users (
    id serial PRIMARY KEY, 
    name varchar(64), 
    username varchar(64), 
    ... 
); 

現在,我希望獲取所有存在的用戶,我希望獲取他們有特定的憑據類型。我試過這個:

ribit=> SELECT u.id, u.name, u.username, ct.name AS cred \ 
     FROM users u, credential_types ct, credentials c \ 
     WHERE c.user_id=u.id AND ct.id=c.credential; 
id | name | username | cred 
----+------+----------+--------- 
    1 | foo | bos  | Try-Out 
(1 row) 

哪種類型的輸出是正確的,但是所有沒有證書的用戶都被省略。我不知道這種操作需要哪種JOIN。我想需要一個LEFT JOIN,但是當我試圖達到我想要什麼,我不能硬:

ribit=> SELECT u.id, u.name, u.username, ct.name \ 
     FROM users u, credential_types ct \ 
     LEFT JOIN credentials c ON ct.id=c.credential; 

給了我一個十字架與erronious數據連接。

我在尋找的是提示如何編寫查詢來產生我想要的輸出。

回答

0

左連接不太合適。

SELECT u.id, u.name, u.username, ct.name 
FROM users u 
LEFT JOIN credentials c ON u.id = c.user_id 
INNER JOIN credential_types ct ON c.credential = ct.id 

我認爲這更接近你想要的。

+0

那一個幾乎工作。因爲它像我的「工作」查詢一樣工作,但是如果我將INNER JOIN更改爲LEFT JOIN(即兩個LEFT JOIN),它會生成我正在努力的輸出。但是,我不知道爲什麼或者發生了什麼,所以我想我不得不再次深入到PG手冊。 謝謝。 – bos

+0

如果兩個左連接工作,很好。唯一的理論區別在於'credentials'中的行不匹配,如果'credential_types'中沒有匹配它們,這看起來是可能的,因爲外鍵約束。在這種情況下,兩者的左連接都應該很好。 – Andrew

0

嘗試

SELECT u.id, u.name, u.username, ct.name 
FROM users u 
LEFT JOIN credentials c ON (u.id=c.user_id) 
JOIN credential_type ct ON ct.id=c.credential; 
0

你可以嘗試先加入憑證表,然後離開加入你的用戶表的結果。

SELECT u.id, u.name, u.username, cred 
FROM users u LEFT JOIN 
(SELECT ct.name AS cred, c.user_id 
    FROM credentials c JOIN credential_types ct ON c.credential=ct.id 
) ON u.id=c.user_id