如何对多列分组后进行排序?——Top10高预订量目的地按工作日统计的SQL查询排序异常问题
解决工作日Top10目的地预订量统计的SQL问题
我明白你想统计每周各工作日里预订量排名前10的目的地(或者每个目的地在各工作日的Top预订数据),先帮你梳理下原SQL的问题,再给出对应解决方案:
原SQL的核心问题
你的查询已经完成了「目的地+工作日」的分组统计,但排序和筛选逻辑没贴合需求:
ORDER BY Destination, count(Destination) desc只是把同一个目的地的所有工作日记录按预订次数降序排列,但没实现「每个工作日取Top10目的地」或者「每个目的地取Top10工作日」的筛选;count(DATENAME(WEEKDAY,BookingDate))其实和COUNT(*)效果完全一致(工作日名称不会为空),用COUNT(*)会更简洁直观。
两种需求场景的正确写法
场景1:每个工作日,取预订次数前10的目的地
这应该是你描述的「每周各工作日预订量排名前10的目的地」核心需求,用窗口函数按工作日分组排名,再筛选前10结果:
-- 第一步:统计每个目的地在各工作日的预订次数 WITH DailyDestStats AS ( SELECT Destination, DATENAME(WEEKDAY, BookingDate) AS Day, COUNT(*) AS Booking FROM Booking GROUP BY Destination, DATENAME(WEEKDAY, BookingDate) ), -- 第二步:按工作日分组,对目的地按预订次数降序排名 RankedDestinations AS ( SELECT *, -- 若要允许并列(比如两个目的地预订次数相同都排第10,都保留),可换成RANK()或DENSE_RANK() ROW_NUMBER() OVER (PARTITION BY Day ORDER BY Booking DESC) AS Rank FROM DailyDestStats ) -- 第三步:筛选每个工作日的前10目的地 SELECT Destination, Day, Booking FROM RankedDestinations WHERE Rank <= 10 -- 最终按工作日、预订次数降序、目的地名称排序 ORDER BY Day, Booking DESC, Destination;
场景2:每个目的地,取预订次数前10的工作日
如果你的需求是看单个目的地在哪些工作日的预订量最高,取前10记录,只需调整窗口函数的分组字段:
WITH DailyDestStats AS ( SELECT Destination, DATENAME(WEEKDAY, BookingDate) AS Day, COUNT(*) AS Booking FROM Booking GROUP BY Destination, DATENAME(WEEKDAY, BookingDate) ), RankedDays AS ( SELECT *, ROW_NUMBER() OVER (PARTITION BY Destination ORDER BY Booking DESC) AS Rank FROM DailyDestStats ) SELECT Destination, Day, Booking FROM RankedDays WHERE Rank <= 10 ORDER BY Destination, Booking DESC, Day;
匹配你给出的示例结果
看你提供的示例结构(每个目的地内部按预订次数降序排列工作日),如果不需要筛选Top10(示例仅展示了3个工作日),可以去掉排名筛选部分,直接排序即可:
SELECT Destination, DATENAME(WEEKDAY, BookingDate) AS Day, COUNT(*) AS Booking FROM Booking GROUP BY Destination, DATENAME(WEEKDAY, BookingDate) ORDER BY Destination, Booking DESC;
内容的提问来源于stack exchange,提问作者Seckinyilmaz
相关产品推荐
相关产品推荐

