关系划分

relational 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)

我知道我应该使用除法。

这是我的答案,但我遇到了一些无法解决的奇怪语法错误。

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)
                )
     );

错误:misuse of aggregate function COUNT()

您可以找到数据库的架构 here

您似乎在错误的地方使用了计数

将 having 用于聚合函数

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

但要确定别名,因为在某些数据库中,别名在子查询中不可用..

您不能为 table 列表起别名,例如 (Album Al, Track T),这是 (Album Al CROSS JOIN Track T) 的过时语法。您可以为 table 添加别名,例如Album Al 或子查询,例如(SELECT * FROM Album CROSS JOIN Track) AS R2.

所以首先你应该把你的连接弄直。我不认为您正在学习那些旧的逗号分隔连接,而是从一些旧书或网站上获得的?请改用适当的显式连接。

那么你不能使用WHERE COUNT(R1.TrackId) = COUNT(R3.TrackId)COUNT是聚合函数,聚合在WHERE之后进行。

关于查询:比较曲目数是个好主意。那么让我们一步一步来吧。

查询以获取每张专辑的曲目数:

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

查询以获取每个客户和专辑的曲目数:

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;

完成查询:

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;

您应该简化您的查询。看看这个:

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

我使用了两个子选择,第一个计算每个客户和专辑的开票曲目,然后将它与另一个子选择连接起来,用于每个专辑和其中的曲目数量,只有在两个计数相等的情况下。

这个好像没那么复杂:

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
)

在更简单的基础上测试了这个想法并扩展到你的例子,所以我不保证你可以复制和粘贴并立即工作...