[英]SQL - Query - max(count())
我正在攻讀我的數據庫系統考試(明天),我在練習中遇到麻煩,我被要求編寫查詢。 這是一個例子:
我被要求寫一個查詢來回答以下問題:年齡最低的作者中,誰寫的書最多?
問題是我的老師禁止我在FROM子句中使用子查詢,並使用TOP 。
我寫了一個答案,但我知道的是不正確的:
SELECT W.AName, COUNT(W.ID_B) AS NBooks
FROM Write W, Author A1
WHERE (A1.AName = W.AName) AND
(A1.AAge = (SELECT MIN(A2.Age)
FROM Author A2))
GROUP BY W.AName
ORDER BY NBooks DESC
這個給所有作者提供較低的年齡,以及他們各自的書籍數量(我希望......)。 正確的答案應該只是這一行的第一行。
讓我說清楚一下:
Table Author
AName | AAge
---------------
John | 25
Rick | 30
Sean | 26
Lena | 25
Table Writes
AName | ID_B
---------------
John | 2
Lena | 1
John | 3
Lena | 4
Rick | 5
Rick | 6
Lena | 6
Rick | 7
Rick | 8
(注意肖恩沒有寫任何書,第6本書有2位作者,而里克是大多數書籍的作者(4))
現在,我上面寫的代碼給出了這個結果(我猜):
AName | NBooks
-----------------
Lena | 3
John | 2
(最低年齡為25歲,Lena和John均為25歲)
問的是:
AName | NBooks
-----------------
Lena | 3
(Lena是作者,所有年齡最小的作者(25),大多數書籍都寫過)
提前致謝
因為你是學生,我會回答部分問題。 這是一個答案,忽略了最年輕的部分:
select a.AName, COUNT(*) as NumBooks
from Author a join
Write w
on a.AName = w.AName
group by a.AName
having count(*) >= all(select COUNT(*) as NumBooks
from write w
group by w.AName
)
我想你可以弄清楚如何修改它。
順便說一句,我希望, limit
和top
的限制只適用於這個例子。 否則,你應該得到另一位老師,因為這些是非常重要的結構。
此外,你需要學習傳統的連接語法,而不是,
在from
子句。 再一次,如果你的老師沒有教授現代化的sytnax(自1988年左右起),請找一位新老師。 並且,我假設對子查詢的限制也適用於CTE。
我還想指出查詢的“正確”版本:
select top 1 a.aname, count(*) as NumBooks
from Author a join
Write w
on a.AName = w.AName
group by author.name, author.Aage
order by author.Age asc, count(*) desc
此查詢幾乎可以在任何維度上比上面的查詢更好。 它做一個join
,一個group by
和一個group by
。 我查詢的完整版本做了兩join
小號明確,兩名join
小號隱含(年齡條款),兩個group by
秒。 前者的表現要比后者好。
從可讀性的角度來看,這個版本更短更清潔。 我也認為教這是做什么要容易得多,而不是第一版中的“不尋常”結構。 大多數學生將了解top
和order by
正在做什么,並可以模仿這一點。 模仿,在發生的事情having
條款要求一些心理體操。
如果你想得到所有作者的最大數量,首先要意識到前面的查詢相當於:
select aname, NumBooks
from (select a.aname, count(*) as NumBooks,
row_number() over (partition by author.Name order by a.aAge, count(*) desc) as seqnum
from Author a join
Write w
on a.AName = w.AName
group by author.name, author.Aage
) aw
where seqnum = 1
切換這個以獲得所有作者很容易:
select aname, NumBooks
from (select a.aname, count(*) as NumBooks,
dense_rank() over (partition by author.Name order by a.aAge, count(*) desc) as seqnum
from Author a join
Write w
on a.AName = w.AName
group by author.name, author.Aage
) aw
where seqnum = 1
這也比回答問題的查詢更有效。 無法在from
子句中使用top
或子查詢就像是在進行三條腿競賽。 是的,你可以到達那里,但是你可以用自己的兩條腿跑得更快。
這是一些限制,但它使人們利用它的創造力。
所以你想要最年輕的作家之一,寫了一些高於(或等於)其他最年輕作家的書籍的書籍......
SELECT
[a1].[AName],
[a1].[AAge],
COUNT(*) AS [NBooks]
FROM [Author] [a1], [Writes] [w1]
WHERE
[a1].[AName] = [w1].[AName]
AND [a1].[AAge] = (SELECT MIN([a2].[AAge]) FROM [Author] [a2])
GROUP BY
[a1].[AName],
[a1].[AAge]
HAVING COUNT(*) >= ALL
(SELECT
COUNT(*) AS [NBooks]
FROM [Author] [a3], [Writes] [w2]
WHERE
[a3].[AName] = [w2].[AName]
AND [a3].[AAge] = (SELECT MIN([a4].[AAge]) FROM [Author] [a4])
AND [a3].[AName] <> [a1].[AName]
GROUP BY
[a3].[AName],
[a3].[AAge])
PS:不得不承認,我了解ALL
的戈登·利諾夫 。
如果您只想要一個結果,請選擇一個結果,然后排序應該完成剩下的工作。 我個人會做一個排名函數,使用Aggregate()Over()窗口函數顯式獲得排名。 但是既然你正在學習,也許他們不想提出這個問題並向你展示“頂級”是如何運作的。
declare @Person Table ( personID int identity, person varchar(8), age int);
insert into @Person values ('Brett', 34),('John', 34),('Peter', 52);
declare @Books Table ( BookID int identity, personID int);
insert into @Books values (1),(1),(1),(2),(2),(3)
Select top 1 -- TOP WILL LIMIT TO CHOICE YOU WANT BASED ON ORDER BY CLAUSE
p.person
, p.age
, count(b.BookID) as cnts
from @Person p, @Books b
where p.personID = b.personID
group by p.person, p.age
order by age, cnts desc
據我所知,你只想要一行;
您可以先限制作者,然后使用內部聯接,您可以從Write表中檢索他的名字和書籍數量。
SELECT W.AName, COUNT(W.ID_B) AS NBooks
FROM Write W INNER JOIN Author A1 ON A1.AName = W.AName
WHERE
A1.AName = (SELECT AName FROM Write GROUP BY AName ORDER BY COUNT(ID_B) DESC)
AND A1.AAge = (SELECT MIN(A2.Age) FROM Author A2)
GROUP BY W.AName
ORDER BY NBooks DESC
如果你被允許使用CTE和RANK它的繁瑣。
WITH cte
AS (SELECT a.aname,
A.aage,
Count(id_b) Book_Count,
RANK()
OVER(
ORDER BY a.aage, Count(id_b) DESC ) rn
FROM author a
INNER JOIN writes w
ON a.aname = w.aname
GROUP BY a.aname,
a.aage)
SELECT aname,
Book_Count
FROM cte
WHERE rn = 1
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.