Problem mit SQL Abfrage 'Not In'

mustangsls

Benutzer
Beiträge
6
Guten Tag.

Bin neu hier und komm jetzt öfter.
Darf mich im Wirtschaftsinformatik Studium mit dem SQL Developer auseinandersetzen und hab noch ein paar Startschwierigkeiten. Hoffe ich finde hier jetzt regelmäßig Hilfe. Stehe auch gern mit Tips zur Verfügung wenn ich selbst welche geben kann.

So nun zum Problem:

Ich möchte mehrere Playlists mit dem Namen 'Classical %' nach Tracks des Genres 'Classical' durchsuchen, die nicht in diesen Playlists auftauchen.

Soweit bin ich bisher, stehe aber jetzt irgendwie auf dem Schlauch:

select tr.name
from track tr,
genre ge,
playlist pl
where pl.name = 'Classical%' and
ge.name not in ('Classical')
;

Ich hänge das passende Modell mal mit an.

Achso, es muss nicht unbedingt mit 'Not In' gelöst werden, erschien mir nur sinnvoll.
 

Anhänge

  • ScreenClip.png
    ScreenClip.png
    34 KB · Aufrufe: 3
Werbung:

PLSQL_SQL

SQL-Guru
Beiträge
176
Hy,

dein SQL-Stmt ist nicht schlecht, jedoch solltest du die Relationen (Beziehungen) des angehängten Modells in deiner Abfrage berücksichtigen!!!
Ansonsten joinst du ALLE Datensätze der 3 Tabellen mit ALLEN der 3 Tabellen. Weiters fehlt dir noch die Tabelle "PLAYLISTTRACK", da du nur über diese von einem Track zur Playlist kommst, denn EINE Playlist kann mehrere Track beinhalten, und EIN Track kann in mehreren Playlists sein!

Daraus folgt: M:N - Beziehung und diese muss (wie es eh schon richtig ist) aufgelöst werden. Somit musst du die Tabelle "PLAYLISTTRACK" mit berücksichtigen!

So.... so viel zu Erklärung, hoffentlich einigermaßen verständlich...

Hier dein Stmt:

Code:
Select pl.Name AS PlaylistName
          tr.Name AS TrackName
 
  FROM PlayList pl
            ,PlayListTrack plt
            ,Track tr
            ,Genre ge
 
--die Beziehungen (Joins) der Tabellen
where pl.PlayListID = plt.PlayListID
AND plt.TrackID = tr.TrackID
AND tr.GenreID = ge.GenreID
 
--deine gewünschte Filterung kommt ab hier
AND pl.Name LIKE 'Classical%' --nur jene Playlists, welche mit dem Wort "Classical" beginnen
AND ge.Name LIKE 'Classical' --nur jene Tracks, welche dem Genre "Classical" zugewiesen sind!

passt dieses Query für dich, oder habe ich das richtig verstanden, dass du ALLE Tracks möchtest, welche als Genre "Classical" zugeordnet haben, jedoch in KEINER Playlist beginnend mit "Classical" sitzen?

LG
 

mustangsls

Benutzer
Beiträge
6
Hallo :)
Das funktioniert ja schonmal blendend. Vielen Dank.

Aber ja, du hast es richtig verstanden. Ich brauche alle 'Classical'-Tracks die nicht in den 'Classical 101'-Playlists sind.

Also so funktioniert es schonmal nicht richtig:

Code:
Select tr.Name
 
FROM PlayList pl,
 
PlayListTrack plt,
 
Track tr,
 
Genre ge
 
where pl.PlayListID = plt.PlayListID AND
 
plt.TrackID = tr.TrackID AND
 
tr.GenreID = ge.GenreID AND
 
pl.Name LIKE 'Classical%' AND
 
ge.Name not in ('Classical')
 
;
 

mustangsls

Benutzer
Beiträge
6
Bin jetzt soweit, das ich ne Unterabfrage brauch. Hänge jetzt soweit noch fest:

Code:
Select  tr.name       
FROM    Track tr, Genre ge 
where  ge.name = 'Classical'
AND    tr.name NOT IN
        ( select tr.name 
          from    track tr, 
                  PlayList pl, 
                  PlayListTrack plt 
          where  pl.Name LIKE 'Classical%')
;
 

mustangsls

Benutzer
Beiträge
6
Geschafft!!! Der Hirnknoten ist endlich geplatzt ;-)

Code:
Select  tr.name       
FROM    Track tr, Genre ge 
where  ge.name = 'Classical'
AND    tr.GenreID = ge.GenreID
AND    tr.name NOT IN
        ( select tr.name 
          from    track tr, 
                  PlayList pl, 
                  PlayListTrack plt 
          where  pl.Name LIKE 'Classical%'
          AND pl.PlayListID = plt.PlayListID
          AND plt.TrackID = tr.TrackID)
;
 

PLSQL_SQL

SQL-Guru
Beiträge
176
Perfekt!!! Super!!!

Aber aus schönheitstechnischen und/oder performance-Gründen würde ich anstatt des Track-Namens die TrackID heranziehen.

Code:
Select tr.name
FROM Track tr, Genre ge
where ge.name = 'Classical'
AND tr.GenreID = ge.GenreID
AND tr.TrackID NOT IN
( select tr.TrackID
from track tr,
PlayList pl,
PlayListTrack plt
where pl.Name LIKE 'Classical%'
AND pl.PlayListID = plt.PlayListID
AND plt.TrackID = tr.TrackID)
;

Noch besser als "NOT IN" ist "NOT EXISTS"


Code:
Select tr.name
FROM Track tr, Genre ge
where ge.name = 'Classical'
AND tr.GenreID = ge.GenreID
AND NOT EXISTS
( select 1 --hier ist egal was du in die Select-Klause schreibst, da die Unterabfrage nur verwendet wird, um zu prüfen, ob etwas existriert oder nicht
from track trsub,
PlayList plsub,
PlayListTrack pltsub
where plsub.Name LIKE 'Classical%'
AND plsub.PlayListID = pltsub.PlayListID
AND pltsub.TrackID = tr.TrackID --Join der Subabfrage mit der äußeren!!!
)
;

LG
 
Werbung:
Oben