2016-05-19 14 views
1

Ich soll eine Abfrage für diese Aussage schreiben:relationale Division

List the names of customers, and album titles, for cases where the customer has bought the entire album (i.e. all tracks in the album)

Ich weiß, dass ich Abteilung sollte.

Hier ist meine Antwort, aber ich bekomme einige seltsame Syntaxfehler, die ich nicht lösen kann.

SELECT 
    R1.FirstName 
    ,R1.LastName 
    ,R1.Title 
FROM (Customer C, Invoice I, InvoiceLine IL, Track T, Album Al) AS R1 
WHERE 
    C.CustomerId=I.CustomerId 
    AND I.InvoiceId=IL.InvoiceId 
    AND T.TrackId=IL.TrackId 
    AND Al.AlbumId=T.AlbumId 
    AND NOT EXISTS ( 
      SELECT 
       R2.Title 
      FROM (Album Al, Track T) AS R2 
      WHERE 
       T.AlbumId=Al.AlbumId 
       AND R2.Title NOT IN (
        SELECT R3.Title 
        FROM (Album Al, Track T) AS R3 
        WHERE 
         COUNT(R1.TrackId)=COUNT(R3.TrackId) 
       ) 
    ); 

ERROR: misuse of aggregate function COUNT()

Sie das Schema für die Datenbank finden here

+3

Am Ende fehlt eine geschlossene Klammer.(Zwei offene Unterabfragen, eine schließende Klammer) –

+0

'(AUSWÄHLEN R2.Titel FROM (Album Al, Track T) AS R2" scheint mir gefallen. Willst du einen Cross-Join zwischen Album und Track machen? – xQbert

+0

habe ich behoben Klammer, aber ich bekomme immer noch diesen Fehler jetzt 'Missbrauch der Aggregatfunktion COUNT()' @Aaron D – RedHood148

Antwort

2

Sie können keine Alias-Liste wie (Album Al, Track T) erstellen, die eine veraltete Syntax für (Album Al CROSS JOIN Track T) ist. Sie können entweder eine Tabelle, z. Album Al oder eine Unterabfrage, z.B. (SELECT * FROM Album CROSS JOIN Track) AS R2.

Also zuerst sollten Sie Ihre Verbindungen gerade erhalten. Ich gehe nicht davon aus, dass dir diese alten kommaseparierten Joins beigebracht werden, sondern sie von einem alten Buch oder einer alten Website bekommen haben. Verwenden Sie stattdessen geeignete explizite Joins.

Dann können Sie WHERE COUNT(R1.TrackId) = COUNT(R3.TrackId) nicht verwenden. COUNT ist eine Aggregatfunktion und die Aggregation erfolgt nach WHERE.

Zur Abfrage: Es ist eine gute Idee, Spur zählt zu vergleichen. Also machen wir das Schritt für Schritt.

Abfrage der Spurzahl pro Album zu bekommen:

select albumid, count(*) 
from track 
group by albumid; 

Abfrage der Spuranzahl pro Kunde und Album zu erhalten:

select i.customerid, t.albumid, count(distinct t.trackid) 
from track t 
join invoiceline il on il.trackid = t.trackid 
join invoice i on i.invoiceid = il.invoiceid 
group by i.customerid, t.albumid; 

komplette Abfrage:

select c.firstname, c.lastname, a.title 
from 
(
    select i.customerid, t.albumid, count(distinct t.trackid) as cnt 
    from track t 
    join invoiceline il on il.trackid = t.trackid 
    join invoice i on i.invoiceid = il.invoiceid 
    group by i.customerid, t.albumid 
) bought 
join 
(
    select albumid, count(*) as cnt 
    from track 
    group by albumid 
) complete on complete.albumid = bought.albumid and complete.cnt = bought.cnt 
join customer c on c.customerid = bought.customerid 
join album a on a.albumid = bought.albumid; 
+0

Ich mag die Art, wie Sie das Problem angehen. Ich führe die Abfrage aus, aber ich bekomme 'mehrdeutigen Spaltennamen: trackid: '@ thorsten-kettner – RedHood148

+0

Ich habe das korrigiert, indem ich t.trackid hinzugefügt habe. jetzt bekomme ich 'keine solche Spalte: c.firstname' – RedHood148

+1

Richtig, ich habe das Qualifikationsmerkmal für trackid vergessen. Aber was meinen Vornamen angeht, bin ich nicht in der Spur. Wir treten dem Tischkunden bei, rufen dieses c auf und wählen seinen Spaltenvornamen aus. Oder existiert diese Spalte nicht? Ist es vielleicht ein Tippfehler in Ihrer Anfrage und der richtige Name ist first_name oder ähnliches? Überprüfen Sie die Kundentabelle, wenn eine Spalte mit diesem Namen vorhanden ist. –

1

Scheint Sie Zählung an der falschen Stelle

Verwendung für Aggregatfunktion mit

SELECT R3.Title 
    FROM (Album Al, Track T) AS R3 
    HAVING COUNT(R1.TrackId)=COUNT(R3.TrackId)) 
verwenden

aber sicher sein, alias bec In einigen Datenbanken ist der Alias ​​nicht in der Unterabfrage verfügbar.

+0

Gut entdeckt, aber das wird immer noch nicht funktionieren. Da die Spur-IDs natürlich nicht null sind, ist HAVING COUNT (R1.TrackId) = COUNT (R3.TrackId) gleich "HAVING COUNT (*) = COUNT (*)", was wiederum gleichbedeutend mit a ist 'HAVING'-Klausel überhaupt. –

0

Sie sollten vereinfachen Sie Ihre Abfrage. Werfen Sie einen Blick auf diesem:

SELECT FirstName 
    , LastName 
    , Title 
FROM (
    SELECT C.FirstName 
     , C.LastName 
     , A.AlbumID 
     , A.Title 
     , COUNT(DISTINCT TrackID) as TracksInvoiced 
    FROM Customer C 
    INNER JOIN Invoice I 
    ON I.CustomerId = C.CustomerId 
    INNER JOIN InvoiceLine IL 
    ON I.InvoiceId = IL.InvoiceId 
    INNER JOIN Track T 
    ON T.TrackID = I 
    INNER JOIN Album A 
    ON A.AlbumID = T.AlbumID 
    GROUP BY C.FirstName, C.LastName, A.AlbumID, A.Title 
) C 
INNER JOIN (
    SELECT AlbumID 
     , COUNT(TrackID) as TotalTracks 
    FROM Track 
    GROUP BY AlbumID 
) A 
ON C.AlbumID = A.AlbumID 
AND TracksInvoiced = TotalTracks 

habe ich zwei Subselects, die ersten Zählungen in Rechnung gestellte Spuren pro Kunden und Album und verbinden es mit einem anderen subselect für jedes Album und Menge von Spuren auf sich, nur dort, wo die beiden Zählungen gleich.

0

Dies scheint etwas weniger kompliziert zu sein: zu Ihrem Beispiel

SELECT r.FirstName, r.LastName, r.Title FROM 
(
    SELECT C.FirstName as FirstName, 
      C.LastName as LastName, 
      A.Title as Title, 
      A.AlbumId as AlbumId, 
      COUNT(*) as count 
    FROM Customer C, Invoice I, InvoiceLine IL, Track T, Album A 
    WHERE C.CustomerId=I.CustomerId 
     AND I.InvoiceId = IL.InvoiceId 
     AND T.TrackId = IL.TrackId 
     AND A.AlbumId = T.AlbumId 
    GROUP BY C.CustomerId, A.AlbumId 
) AS r 
WHERE r.count IS IN 
(
    SELECT COUNT(*) FROM Track T 
    WHERE T.AlbumId = r.AlbumId 
) 

testete die Idee auf eine einfachere Basis und erweitert, so dass ich keine Garantie geben, die Sie kopieren und einfügen können und ihre funktioniert sofort ...

+0

Ihre Anfrage ist nicht korrekt. Sie vermissen 'A.AlbumId' in Ihrer' GROUP BY'-Klausel. Und Sie sollten keine korrelierten IN-Klauseln verwenden. Verwenden Sie entweder ein korreliertes "EXISTS" oder ein nicht-korreliertes "IN", um den Leser nicht zu verwirren. Die Verbindung zu Album in der IN-Klausel ist übrigens überflüssig. –

+0

Danke für die Hinweise - konnte die Abfrage nicht versuchen, war als Hinweis gedacht, eine Lösung zu finden, solange keine besseren Antworten existierten ... – Aconcagua