2016-11-18 1 views
0

Предположим, у меня есть эта схема базы данных:SQL: Как утверждать, что ни один элемент набора не может присутствовать в другом наборе?

schema

Я наткнуться на этот вопрос более чем на один час: «Выбрать все альбомы которых нет дорожки не были использованы в списке воспроизведения».

Я хочу сделать что-то вроде этого:

SELECT parentalbum.albumid FROM album AS parentalbum 
    INNER JOIN track 
    ON track.albumid = parentalbum.albumid 
    INNER JOIN playlistitem 
    ON track.trackid = playlistitem.trackid   // Join the 3 tables 
    WHERE NOT ((SELECT track.trackid FROM album 
       INNER JOIN track 
        ON album.albumid = track.albumid 
       WHERE track.albumid = parentalbum.albumid) // Select songs from one album 
      IN playlistitem.trackid )     // Check if at least one element of the album is in a playlist? (faulty) 

Мой запрос, вероятно, совершенно неправильно, поэтому я был бы признателен за любую помощь.

EDIT: Я забыл упомянуть, меня попросят решить это, используя коррелированные подзапросы. Спасибо!

+0

Какая СУБД вы используете? –

ответ

1

NOT EXISTS() ответ:

SELECT *  -- Select all albums 
FROM album a 
WHERE NOT EXISTS (  -- of which no track 
    SELECT * FROM track t 
    WHERE t.albumid = a.albumid 
    AND EXISTS (
     SELECT * FROM playlistitem pi -- has been used in a playlist 
     WHERE pi.trackid = t.trackid  
     ) 
    ) 
     ; 

Еще проще:

SELECT *  -- Select all albums 
FROM album a  
WHERE NOT EXISTS (  -- of which no track 
     SELECT * 
     FROM track t -- has been used in a playlist 
     JOIN playlistitem pi ON t.trackid = pi.trackid 
     WHERE t.albumid = a.albumid 
     ) 
     ; 
1

Используйте left join для соединения таблиц свободно. Затем группа по альбомам и принимать только те, которые имеют нулевые дорожки в playlistitem таблицы

select a.id, a.title 
from album a 
left join track t on t.albumid = a.albumid 
left join playlistitem pi on pi.trackid = t.trackid 
group by a.id, a.title 
having sum(case when pi.trackid is not null then 1 else 0 end) = 0 
+0

Спасибо, однако это упражнение специально просит использовать коррелированные подзапросы (отредактирует вопрос) - как я могу решить его таким образом? – Gloomy

0

Первой создать подзапрос, который имеет внутреннее соединение объединиться все результаты, которые соединены в следе и playlistitem. Затем проверьте, нет ли в этом списке альбумида. Я использовал отдельные, чтобы получить только уникальные значения альбумида в подзапросе.

SELECT a.albumid 
FROM album a 
WHERE a.albumid NOT IN 
( SELECT DISTINCT t.albumid 
    FROM track t 
    INNER JOIN playlistitem p 
    ON p.trackid = t.trackid 
) 
+0

К сожалению, кажется, что этот ответ не использует коррелированный подзапрос, который был запрошен. – mendosi

+0

Правда, если необходимы коррелированные подзапросы, лучшим ответом будет использование NOT EXISTS(), как указано в другом ответе. – Alexandervc

+0

'distinct' is ** not ** a функция - помещение столбца между круглыми скобками абсолютно бесполезно –

0

Альтернативный вариант, который использует связанный подзапрос, но не использует NOT EXISTS, только потому, что ...

Select a.* 
    From Album As a 
    Where 0 = (
    Select Count(*) 
     From PlaylistItem As pi 
     Join Track As t on pi.TrackID = t.TrackID 
     Where t.AlbumID = a.AlbumID); 
Смежные вопросы