我正在为我的数据库系统考试(明天)学习,我在练习中遇到麻烦,我被要求编写查询.以下是一个例子:
我被要求写一个查询来回答以下问题:在最低年龄的作者中,谁写大部分书籍?
问题是我的老师禁止我使用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
(注意,肖恩没有写任何书,书中有2位作者,而里克是大多数书籍的作者(4))
现在,我上面写的代码给出了这个结果(我猜)
AName | NBooks ----------------- Lena | 3 John | 2
(最低年龄25岁,莱娜和约翰都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 )
我想你可以弄清楚如何修改它.
顺便说一句,限制和限制是我希望只有这个例子.否则,你应该得到另一位老师,因为这些都是非常重要的结构.
另外,您需要学习常规的连接语法,而不是在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
这个查询比几乎任何维度上面的查询都好.它一个连接,一组和一个.我的查询的完整版本明确地进行了两个连接,两个连接隐含(age子句)和两个组旁边.前者将比后者有更好的表现.
从可读性的角度来看,此版本更短,更干净.我也认为,教导这是做什么,而不是第一个版本中的“不寻常的”结构要容易得多.大多数学生将会了解什么顶级和顺序正在做,并可以效仿这一点.模拟发生在那个条款中需要一些精神体操.
如果要让所有作者获得最大数量,首先要意识到以前的查询相当于:
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,dense_rank() over (partition by author.Name order by a.aAge,author.Aage ) aw where seqnum = 1
这也比回答问题的查询效率更高.无法在from子句中使用top或subqueries就像运行一个三足的比赛.是的,你可以到达那里,但是你可以在自己的两条腿上跑得更快.