SQL BillingState!= CA

Я был на этом в течение нескольких часов и у меня проблемы с логикой.

Вопрос задает вопрос: найдите плейлист, в котором есть один или несколько треков, которые никогда не были куплены в Калифорнии (Калифорния). Распечатайте Id и название таких плейлистов.

Наборы отношений можно найти здесь:

https://chinookdatabase.codeplex.com/wikipage?title=Chinook_Schema&referringTitle=Documentation

Мои решения ничего не возвращают, и я прав или нет, понятия не имею. Если мое решение неверно, где ошибка в моей логике? И если это неправильно, то как правильно подходить к этой проблеме (решение будет предпочтительнее с объяснением)

Мое решение:

 Select DISTINCT  P.PlaylistId, P.Name, I.BillingState
From Playlist P, Invoice I, Track T
Where  P.PlaylistId IN (
    Select PT.PlaylistId
    From PlaylistTrack PT
Where PT.TrackId IN(
    Select T.TrackId
    From Track T
    Where T.TrackId IN(
        Select IL.InvoiceLineId
        From InvoiceLine IL
        Where IL.InvoiceId IN(
            Select I.InvoiceId
            FROM Invoice I
            WHERE I.BillingState = 'CA'
            Group by I.InvoiceId
            Having COUNT(I.InvoiceId) < 1))))
Group By T.TrackId
HAVING COUNT (T.TrackId) > 1

2 ответа

Решение

Позвольте мне объяснить, почему ваш код не работает. (У Даррена вполне разумный ответ.)

        Select I.InvoiceId
        FROM Invoice I
        WHERE I.BillingState = 'CA'
        Group by I.InvoiceId
        Having COUNT(I.InvoiceId) < 1

Этот подзапрос логически некорректен. Он всегда вернет пустой набор. Зачем? Вы ограничиваете счета для тех, которые имеют CA, Следовательно, каждый счет будет иметь по крайней мере одну строку перед GROUP BY, Следовательно HAVING предложение отфильтрует все.

Вы хотите условную агрегацию:

        Select I.InvoiceId
        FROM Invoice I
        Group by I.InvoiceId
        Having SUM(CASE WHEN I.BillingState = 'CA' THEN 1 ELSE 0 END) = 0;

Но вам, вероятно, не нужно агрегировать по InvoiceId, Это должно быть уникальным. Итак, как насчет:

        SELECT I.InvoiceId
        FROM Invoice I
        WHERE I.BillingState <> 'CA'

Я бы использовал JOIN,

SELECT PlayListId, Name
FROM PlayList PL
INNER JOIN PlayerListTrack PLT ON PLT.PlayListId = PL.PlayListId
INNER JOIN Track T ON T.Trackid = PLT.TrackId
INNER JOIN InvoiceLine IL ON IL.TrackId = T.TrackID
INNER JOIN Invoice I ON I.InvoiceId = IL.InvoiceId
WHERE I.BillingState != 'CA'

Это объединяет все таблицы соответственно и отфильтровывает таблицу счетов-фактур (столбец BillingState), где значения не равны Калифорнии.

Другие вопросы по тегам