Я работаю над базой данных с таблицами, перечисленными ниже:
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) этот конкретный вход разрешен для клиента.
Глядя на код yuor, вы могли бы избежать условия if, используя только подходящие где и AND
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 cer1.idCustomer IS NULL
AND cer2idEntrance IS NOT NULL AND cer2.idCustomer = cu.idCustomer