Mysql
如何根據查詢結果是否具有來自另一個表的所有值來過濾查詢結果?
例如,使用者可以執行的某些操作需要一組權限。
使用者儲存在使用者表中:
和權限表中的權限。使用者可以擁有權限 A、B 或兩者兼有。
所需權限儲存在RequiredPermissions 中。由此,POST 操作需要權限 A 和 B
我想查詢所有可以 POST 的使用者(使用者 1)。此查詢將為具有任何權限的使用者(即使用者 1 和 2)提供:
select distinct u.UserId from Users as u join RequiredPermissions as rp on rp.ActionType = "POST" join Permissions as p on u.UserId = p.UserId
如何使用此架構查詢同時具有權限 A 和 B 的使用者?
與更典型的聯接和聯合相比,關係除法是一種不太常見的查詢類型。在 SQL 中有點尷尬。
您想知道擁有 POST 所需的所有權限的使用者。
另一種表述方式是返回其權限中缺少 POST 所需權限的使用者。
SELECT u.UserID FROM Users AS u WHERE NOT EXISTS ( SELECT * FROM RequiredPermissions AS rp LEFT OUTER JOIN Permissions AS p ON rp.Permission = p.Permission AND u.UserId = p.UserId WHERE rp.ActionType = 'POST' AND p.UserId IS NULL)
p.*
它的工作方式是如果沒有匹配,則 OUTER JOIN 將變為NULL。因此,如果外部查詢不希望出現所需權限與相應使用者不匹配的情況,則該使用者必須具有所有所需權限。這會自動處理具有 3 個或更多權限的操作。我見過的其他關係劃分解決方案要求您對要搜尋的項目數的查詢進行程式碼更改。
在 SQL 中進行關係除法基本上有兩種方法。第一個版本由 Bill Karwin 描述,並將 De Morgan 定律擴展到謂詞邏輯:
FORALL p(x) == NOT EXISTS NOT p(x)
nbk 描述的另一個版本將域的基數與每個使用者的基數進行比較。就像是:
SELECT userid FROM Permissions JOIN RequiredPermissions USING (permission) GROUP BY userid HAVING COUNT(distinct ActionType) = (SELECT COUNT(distinct ActionType) FROM RequiredPermissions);
後者更容易概括為“哪些使用者擁有超過 X% 的……”之類的查詢。
SELECT userid FROM Permissions JOIN RequiredPermissions USING (permission) GROUP BY userid HAVING COUNT(distinct ActionType) >= 0.4*(SELECT COUNT(distinct ActionType) FROM RequiredPermissions);