我在SO上看到过几篇文章,它们涉及在由另一个属性分组的一个属性中选择最大值,但是我无法复制结果,而且我不确定自己在做什么错。
我收到一条SQL异常,提示我检查我的SQL版本手册(使用MySQL)。
关系
我正在尝试SELECT
的用户ID和2018年最受欢迎的歌曲(按名称)。我的尝试在下面。
我的基本原理是获得按用户ID(UID
)和每首歌曲按歌曲ID(SID
)分组的关系以及每首歌曲的计数,然后加入歌曲名称并过滤MAX
有价值,但是我在这里遗漏了一些重要的东西,并且将我的答案与其他类似问题的SO帖子进行比较并没有太大帮助
SELECT UID, SName
FROM
(SELECT UID, SName, COUNT(listenDate) AS listen_date_count
FROM record
LEFT JOIN song ON song.SID = record.SID
WHERE YEAR(Date) = 2018
GROUP BY UID, SName) AS records_2018
GROUP BY UID, SName
HAVING MAX(listen_date_count);
答案 0 :(得分:0)
这是在子查询中按用户/歌曲元组进行聚合的良好起点。我只需添加一个NOT EXISTS
条件,以确保没有其他具有最高视图计数的元组。
以下查询应为您提供2018年每个用户观看次数最多的歌曲:
SELECT *
FROM (
SELECT r.UID, r.SID, s.SName, COUNT(*) AS listen_date_count
FROM record r
INNER JOIN song s ON s.SID = r.SID
WHERE YEAR(r.Date) = 2018
GROUP BY r.UID, r.SID, s.SName
) x WHERE NOT EXISTS (
SELECT 1
FROM record r1
WHERE YEAR(r1.Date) = 2018 AND r1.UID = x.UID AND r1.SID != x.SID
GROUP BY r1.UID, r1.SID
HAVING COUNT(*) > x.listen_date_count
)
PS:
在group by子句中需要SID
;相反,用SName
进行分组是不安全的,因为两个具有相同名称的不同歌曲最终会错误地分组在一起
在使用联接或相关子查询时,您想在列名前加上相关的表前缀。这样可以避免冲突,并通常使事情更易于理解和维护。
答案 1 :(得分:0)
您只能首先LIMIT观看歌曲。
然后选择前1首歌曲,再选择LIMIT(上限)用户。
SELECT usermost.UID, song.SName
FROM
(
SELECT songmost.SID, rec.UID
FROM
(
SELECT SID
FROM record
WHERE YEAR(`Date`) = 2018
GROUP BY SID
ORDER BY COUNT(*) DESC, COUNT(DISTINCT UID) DESC
LIMIT 1
) songmost
JOIN record rec
ON rec.SID = songmost.SID AND YEAR(rec.`Date`) = 2018
GROUP BY rec.SID, rec.UID
ORDER BY COUNT(*) DESC
LIMIT 1
) usermost
LEFT JOIN song ON song.SID = usermost.SID
示例:
CREATE TABLE user ( UID int primary key not null auto_increment, UName varchar(30) not null, State int not null default 0 );
CREATE TABLE artist ( AID int primary key not null auto_increment, AName varchar(30) not null, Description varchar(300) );
create table song ( SID int primary key not null auto_increment, AID int not null, SName varchar(30) not null, ReleaseDate date not null, constraint fk_song_aid foreign key (AID) references artist(AID) );
create table record ( SID int not null, UID int not null, `Date` date not null, constraint fk_record_sid foreign key (SID) references song(SID) );
insert into user (UName, State) values ('John Doe', 0), ('Jane Sheppard', 1);
insert into artist (AName, Description) values ('Imagine Dragons', 'American pop rock band'), ('Yuki Kajiura', 'Japanese musician, composer and record producer');
insert into song (AID, SName, ReleaseDate) values (1, 'Whatever it takes', '2017-10-06'), (2, 'I talk to the rain', '2005-07-05');
insert into record (SID, UID, `Date`) values (1,1,'2018-01-01'),(1,1,'2018-02-01'),(1,2,'2018-03-01'), (2,1,'2018-04-01'),(2,2,'2018-01-01');
select rec.SID, song.SName, user.UName, artist.AName, COUNT(*) As Total from record rec left join song on song.SID = rec.SID left join user on user.UID = rec.UID left join artist on artist.AID = song.AID group by rec.SID, rec.UID
SID | SName | UName | AName | Total --: | :----------------- | :------------ | :-------------- | ----: 1 | Whatever it takes | John Doe | Imagine Dragons | 2 1 | Whatever it takes | Jane Sheppard | Imagine Dragons | 1 2 | I talk to the rain | John Doe | Yuki Kajiura | 1 2 | I talk to the rain | Jane Sheppard | Yuki Kajiura | 1
SELECT usermost.UID, song.SName FROM ( SELECT songmost.SID, rec.UID FROM ( SELECT SID FROM record WHERE YEAR(`Date`) = 2018 GROUP BY SID ORDER BY COUNT(*) DESC, COUNT(DISTINCT UID) DESC LIMIT 1 ) songmost JOIN record rec ON rec.SID = songmost.SID AND YEAR(rec.`Date`) = 2018 GROUP BY rec.SID, rec.UID ORDER BY COUNT(*) DESC LIMIT 1 ) usermost LEFT JOIN song ON song.SID = usermost.SID
UID | SName --: | :---------------- 1 | Whatever it takes
db <>提琴here