Обычно это помогает попытаться записать ваш запрос на простом английском языке (или на любом другом языке, на котором вы говорите).
Вам нужно несколько вариантов:
1) Все публичные песни
2) Все песни из белого списка, где идентификатор пользователя находится в белом списке.
3) Все песни из черного списка, в которых идентификатор пользователя отсутствует в черном списке.
4) Все приватные песни самого пользователя.
Таким образом, четыре условия, что означает:
SELECT
*
FROM
songs
WHERE
(acessType = 'Public')
OR
(acessType = 'Whitelist' AND id IN (
SELECT songID FROM WhiteList WHERE userID = :userID)
)
OR
(acessType = 'Blacklist' AND id NOT IN (
SELECT songID FROM BlackList WHERE userID = :userID)
)
(Кстати, я тоже скопировал вашу орфографическую ошибку!)
Просто и эффективно. И позвольте мне теперь объяснить, почему это работает. В предложении «Где» я делаю четыре подпункта. Поскольку я хочу получить набор результатов из одной таблицы, мне не нужно объединение. Также не нужен союз, так как условия менее сложные, чем я ожидал. (Хотя это помогает сначала разбить запрос на несколько подзапросов.)
Первое условие проверяет личные песни, которые принадлежат пользователю. Вы можете просто пропустить часть "acessType = 'Private' AND", чтобы выбрать все песни, принадлежащие пользователю, независимо от того, входит он в черный список или нет. Если вы не хотите, чтобы частные песни были включены, пропустите это условие!
Второе условие добавляет все публичные песни. У этого нет никаких дополнительных ограничений.
Для третьего условия мне нужно сначала выбрать список песен, к которым пользователь может получить доступ. Таким образом, добавляется дополнительный выбор, и я проверяю идентификаторы в этом списке.
Для четвертого условия мне нужны все идентификаторы песен, которые НЕ находятся в черном списке для конкретного пользователя. Опять же, это дополнительный выбор, но на этот раз идентификатор не должен быть в списке.
В совокупности четыре условия вернут список записей песен, соответствующих вашим пожеланиям. Легко и просто. Не пытайтесь усложнить ситуацию, думая о соединениях, когда все, что вы делаете, это выбираете данные из одной таблицы. Иногда может потребоваться UNION, но требуется JOIN, чтобы объединить несколько таблиц в один результат. Вы этого не хотите!
Кстати,: userID преобразуется в часть параметров запроса. Это имеет тенденцию быть немного специфичным для реализации SQL, а иногда? или что-то еще используется. Просто прочитайте «Параметр идентификатора пользователя», когда увидите: userID.