我一直在研究一个数据库,其表如下所示:
Customer
id INTEGER, PRIMARY KEY
name VARCHAR
Entrance
id INTEGER, PRIMARY KEY
desc VARCHAR
CustomerEntranceRestriction
idEntrance PK, FK to Entrance.id
idCustomer PK, FK to Customer.id
CustomerEntranceRestriction
表仅包含客户仅限于他们可以使用的入口的条目。该表中没有记录的客户可以访问任何入口。
我想尝试返回每个客户可以访问的所有入口。我的查询如下:
SELECT DISTINCT
c.id As customer_id,
e.id AS entrance_id
FROM customer c
JOIN entrance e
LEFT JOIN CustomerEntranceRestriction cer1
ON cer1.idCustomer = cu.id
LEFT JOIN CustomerEntranceRestriction cer2
ON cer2.idEntrance = e.id
WHERE
IF(cer1.idCustomer IS NULL, 0, cer2.idEntrance - e.id) = 0
AND
IF(cer2.idEntrance IS NOT NULL,IF(cer2.idCustomer =cu.idCustomer,0,1),0) = 0
我认为这是正确的,但我对逻辑的把握不够。通过左键加入CustomerEntranceRestriction
在部分主键上两次表,我们可以包含具有 NULL
的行两个匹配的值。当匹配发生在 cer1
上时或cer2
我们检查是否有匹配 c.id
或e.id
,删除失败的行。
这个逻辑合理吗?我不确定这在关系数据库圈子里是否有名字。
另一种方法是交叉连接所有 Customer
和Entrance
CustomerEntranceRestrction
中没有客户的记录和UNION
这些记录在 CustomerEntranceRestriction
中找到表。
如有任何建议,我们将不胜感激。
最佳答案
我想你想要:
SELECT c.id As customer_id,
e.id AS entrance_id
FROM customer c CROSS JOIN
entrance e LEFT JOIN
CustomerEntranceRestriction cer
ON cer.idCustomer = c.id AND cer.idEntrance = e.id
WHERE NOT EXISTS (SELECT 1 FROM CustomerEntranceRestriction cer2 WHERE cer2.idCustomer = c.idCustomer) OR
cer.idEntrance IS NOT NULL;
这从客户和入口的所有组合开始。然后它会引入任何限制。
WHERE
子句表示 (1) 客户没有任何限制,或者 (2) 允许客户进入此特定入口。
关于如果找到行,MySQL 在表上相交,否则忽略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51050115/