2016-06-21 90 views
0

我需要編寫一個查詢,將符合下列條件:如何編寫SQL查詢以從多個表中獲取信息?

考慮(6,8,10)的UID的列表,獲取name_first和具有的權限「管理用戶」的用戶name_last。

CREATE TABLE users (
uid INT(11) AUTO_INCREMENT, 
status TINYINT(3) NOT NULL DEFAULT 1, 
name_first VARCHAR(256) DEFAULT '', 
name_last VARCHAR(256) DEFAULT '', 
email VARCHAR(256) DEFAULT '', 
PRIMARY KEY (`uid`) 
); 

CREATE TABLE role(
rid INT(11) AUTO_INCREMENT, 
name VARCHAR(256), 
PRIMARY KEY `rid` (`rid`) 
); 

CREATE TABLE users_roles (
uid INT(11), 
rid INT(11), 
PRIMARY KEY (`uid`), 
KEY `rid` (`rid`) 
); 

CREATE TABLE permissions (
rid INT(11), 
permission VARCHAR(64), 
UNIQUE KEY (`rid`, `permission`) 
); 

INSERT INTO users (uid, status, name_first, name_last, email) 
VALUES 
(1, 1, 'Joe', 'Montana', ''), 
(2, 1, 'Eli', 'Manning', ''), 
(3, 1, 'Peyton', 'Manning', ''), 
(4, 1, 'Steve', 'Young', ''), 
(5, 1, 'John', 'Elway', ''), 
(6, 1, 'Robert', 'Griffin', ''), 
(7, 1, 'Joe', 'Montana', ''), 
(8, 1, 'Tom', 'Brady', ''), 
(9, 1, 'Drew', 'Brees', ''), 
(10, 1, 'Andrew', 'Luck', ''); 

INSERT INTO role (rid, name) 
VALUES 
(1, 'Teacher'), 
(2, 'Athletic Directory'), 
(3, 'Administrator'); 

INSERT INTO permissions (rid, permission) VALUES 
(1, 'Administer users'), 
(1, 'Administer courses'), 
(1, 'Build Unicorns'), 
(2, 'Administer groups'), 
(3, 'Administer users'), 
(3, 'Administer school'); 

INSERT INTO users_roles (uid, rid) VALUES 
(1, 3), 
(2, 1), 
(3, 3), 
(4, 1), 
(5, 1), 
(6, 2), 
(7, 2), 
(8, 3), 
(10, 1); 

這是我到目前爲止有:

SELECT name_first, name_last FROM users 
JOIN users_roles 
ON users.uid = users_roles.uid 
JOIN role 
ON role.rid = users_roles.rid 
JOIN permissions 
ON users.uid = permissions.rid 
WHERE users.uid = 8 AND permissions.permission = 'Administer users'; 

這是我在寫SQL第一次嘗試,我已經糊塗自己努力使其發揮作用。任何幫助表示讚賞。

+1

檢查你加入條件'users.uid = permissions.rid',你期望這樣做會怎樣? –

+0

不,我進一步查看後,權限表沒有使用uid作爲外鍵。 –

+0

哪種RDBMS適用於? * SQL *是一個標準 - 但供應商經常以不同的方式實現它,所以請添加一個標籤來指定您是使用'mysql','postgresql','sql-server','oracle'還是'db2' - 其他完全。 –

回答

0
ON users.uid = permissions.rid 

應該

ON role.rid = permissions.rid 

因爲如果你想看到你需要使用LEFT JOIN(外連接),而不是INNER JOIN NULL值不是所有的記錄,涉及到其他表。

如果您想查看所有記錄,或者它與INNER JOIN相同,您應該將permission ='admin ...'移至開啓狀態。

SELECT 
    * 
FROM 
    users u 
    LEFT JOIN users_roles ur 
    ON u.uid = ur.uid 
    LEFT JOIN role r 
    ON ur.rid = r.rid 
    LEFT JOIN permissions p 
    ON r.rid = p.rid 
    AND p.permission = 'Administer users' 
WHERE 
    u.uid IN (6,8,10); 
+0

當我擁有users.uid = 8時適用,但我怎樣才能檢查uid 6和10?我寫出了單獨的WHERE語句並出現錯誤。 –

+0

使用左連接而不是內連接,因爲不是所有的用戶都被分配到一個角色和權限 – Matt

+0

我試過你在上面發佈的東西,它沒有工作,它給了我所有的名字和姓氏,而不僅僅是用於uid 6的,8和10. http://sqlfiddle.com/#!9/f6955/314 –

0

我添加了一個額外的列,以防萬一您需要它。我創建臨時表進行測試所以只是從查詢中刪除的哈希標籤:

SELECT 
    U.name_first 
    ,U.name_last 
    ,P.permission PermissionName 
    ,R.name RoleName 
FROM 
    #users U 
    JOIN #users_roles UR 
     ON U.uid= UR.uid 
    LEFT JOIN #role R 
     ON UR.rid = R.rid 
    LEFT JOIN #permissions P 
     ON UR.rid = P.rid 
WHERE 
    U.uid IN (6,8,10) 
    AND P.permission = 'Administer users' 
; 
+1

,因爲你的where子句中有一個限制結果的條件,你有一個LEFT JOIN對你基本上是做一個內部連接。您需要將p.permission ='admin ...'移動到加入的ON條件部分 – Matt

+0

@Matt引用左連接的WHERE子句的使用是內連接是正確的。然而,我這樣做是基於我的假設,我希望看到當我不使用WHERE子句時這些表如何交互。角色和權限表是相互獨立的,所以我使用了兩個左連接。如果您沒有這種需求,或者您的案例沒有任何好處,則可以使用連接。但是,在任何情況下,您都不必將條件從WHERE子句移動到ON條件。它的基礎是第三方閱讀的可能性更大,而且更具動態性。祝你好運! –

+0

@Matt我不反對你。我只能說出過去對我有用的東西。通常最終用戶的需求會發生變化,所以我會盡量平衡代碼的效率和代碼,這些代碼可以根據最終用戶的變化需求快速輕鬆地進行更改。但是,如果我希望在代碼中更簡潔,我可能仍然不會將權限從WHERE子句移動到ON子句,但它可能只是樣式的差異。 –

0

試試這個但你不會得到UID(6),因爲它不具有「管理用戶」權限。

選擇name_first,從用戶name_last其中uid在 (選擇從其中除掉 users_roles UID(選擇權限,其中權限= '管理用戶' RID))和(6,8,10)的UID;

+0

if you need 6 too then UPDATE'users_roles' SET'rid' ='1'WHERE' users_roles'.'uid' = 6; – Rakesh

相關問題