所以,我将通过很多练习进行最后的SQL考试,我在星期四进行了最后一次SQL考试,我遇到了另一个疑问。
练习中的表格应该来自酒店数据库。你有三个表:
STAY ROOM ROOM_TYPE
=========== ============ ============
PK ID_STAY PK ID_ROOM PK ID_ROOM_TYPE
DAYS_QUANT ID_ROOM_TYPE FK DESCRIPTION
DATE PRICE
ID_ROOM FK
他们要求我做的查询是“按房间类型显示2011年租用最多天数(总计)的房间的所有数据(您必须显示房间类型)和描述)“
这是我解决它的方式,我不知道是否可以:
SELECT RT.ID_ROOM_TYPE, RT.DESCRIPTON, R.*, SUM(S.DAYS_QUANT)
FROM STAY S, ROOM R, ROOM_TYPE RT
WHERE YEAR(S.DATE) = '2011'
GROUP BY RT.ID_ROOM_TYPE, RT.DESCRIPTON, R.*
ORDER BY SUM(S.DAYS_QUANT) DESC
LIMIT 1
所以,我不确定的第一件事就是R. *我包括在内。我可以把它放在SELECT中吗?是否也可以像GROUP BY一样包含它?
另一件事我不确定我是否可以在考试中使用LIMIT或SELECT TOP 1语句。谁能想到一种解决这个问题的方法而不使用它们?喜欢MAX()语句还是什么?
答案 0 :(得分:1)
select r.*, t.*
from room r
join room_type t on t.id_room_type = r.id_room_type
where r.id in
(select
(select r.id_room
from room r
join stay on stay.id_room = r.id_room
where year(s.date) = '2011'
and r.id_room_type = t.id_room_type
group by r.id_room
order by sum(s.days_quant) desc
limit 1) room_id
from room_type t)
答案 1 :(得分:1)
始终可以避免LIMIT 1或SELECT TOP。一种方法是将顶行表示为没有较高行的行。什么不存在表达“没有。”的想法。
考虑到这一点的一种方法如下:选择那些没有相同类型的房间且总天数更多的房间(连同它们的总天数和类型信息)。这给你这个查询(不仔细校对):
with StayTotals as (
select
STAY.ID_ROOM,
ROOM_TYPE.ID_ROOM_TYPE,
ROOM_TYPE.DESCRIPTION,
SUM(STAY.DAYS_QUANT) AS TotalDays2011
from STAY join ROOM on STAY.ID_ROOM = ROOM.ID_ROOM
join ROOM_TYPE on ROOM.ID_ROOM_TYPE = ROOM_TYPE.ID_ROOM_TYPE
where YEAR(STAY.DATE) = 2011
group by STAY.ID_ROOM, ROOM_TYPE.ID_ROOM_TYPE, ROOM_TYPE.DESCRIPTION
)
select *
from StayTotals as T1
where not exists (
select *
from StayTotals as T2
where T2.ID_ROOM_TYPE = T1.ID_ROOM_TYPE
and T2.TotalDays2011 > T1.TotalDays2011
);
如果你不能使用CTE(WITH子句),你可以使用子查询重写它,但它很尴尬。
排名函数已经成为SQL标准的一部分了很长一段时间。如果你可以使用它们,这也可能有效:
with StayTotals as (
select
STAY.ID_ROOM,
ROOM_TYPE.ID_ROOM_TYPE,
ROOM_TYPE.DESCRIPTION,
SUM(STAY.DAYS_QUANT) AS TotalDays2011
from STAY join ROOM on STAY.ID_ROOM = ROOM.ID_ROOM
join ROOM_TYPE on ROOM.ID_ROOM_TYPE = ROOM_TYPE.ID_ROOM_TYPE
where YEAR(STAY.DATE) = 2011
group by STAY.ID_ROOM, ROOM_TYPE.ID_ROOM_TYPE, ROOM_TYPE.DESCRIPTION
), StayTotalsRankedByType as (
select
ID_ROOM,
ID_ROOM_TYPE,
DESCRIPTION,
TotalDays2011,
RANK() OVER (
PARTITION BY ID_ROOM_TYPE
ORDER BY TotalDays2011 DESC
) as RankInRoomType
from StayTotals
)
select
ID_ROOM,
ID_ROOM_TYPE,
DESCRIPTION,
TotalDays2011
from StayTotalsRankedByType
where RankInRoomType = 1;
最后,另外一种拉入额外列来描述分组MAX结果的方法是使用“carryalong”排序,这在排名函数可用之前是一种方便的技术。 Adam Machanic给出了一个示例here,来自Usenet的主题有一些有用的主题,例如this one。
答案 2 :(得分:1)
我相信你不能使用CTE,因此我扩展了Steve Kass的答案的最后部分。您可以通过比较一个房间被占用的总天数与任何相同类型的房间被占用的最大总天数来获得没有TOP或限制条款的预期结果。为此,您首先按房间总计天数,然后使用相同的派生表,每个房型最多可获得天数。按房间类型和天数加入两个房间,您将隔离最常用的房间。然后您加入起始表以显示所有数据。与TOP或Limit不同,如果出现平局,这将产生更多记录。
P.S。这是没有测试过的。我相信它会奏效,但可能会有拼写错误。
select r.*, rt.*, roomDays.TotalDays
from Room r inner join Room_type rt
on r.id_room_type = rt.id_room_type
inner join
(select id_room, id_room_type, sum(days_quant) TotalDays
from Stay
inner join Room
on Stay.id_room = Room.id_room
where year(Date) = 2011
group by id_room, id_room_type) roomDays
on r.id_room = roomDays.id_room
inner join
(select id_room_type, max(TotalDays) TotalDays
from
(select id_room, id_room_type, sum(days_quant) TotalDays
from Stay
inner join Room
on Stay.id_room = Room.id_room
where year(Date) = 2011
group by id_room, id_room_type) roomDaysHelper
group by id_room_type) roomTypeDays
on r.id_room_type = roomTypeDays.id_room_type
and roomDays.TotalDays = roomTypeDays.TotalDays
答案 3 :(得分:0)
这个怎么样?
select room.id_room, room_type.description, room.price
from room inner join room_type
on room.id_room.type = room_type.id_room_type
where room.room_id = (select room_id from stay
where year (date) = 2011
group by id_room
order by sum (days_quant) desc);
不幸的是,这个查询(现在是这样)并没有显示多天来最受欢迎的房间被租用了。但是没有'限制1'!
答案 4 :(得分:0)
谢谢大家!有了你给我的所有想法,我想出了这个,请告诉我你是否认为没问题!
SELECT R.ID_ROOM, R.ID_ROOM_TYPE, T.DESCRIPTION, SUM(S.DAYS_CUANT)
FROM ROOM R, ROOM_TYPE T, STAY S
(SELECT ID_STAY, SUM(S.DAYS_QUANT) TOTALDAYS
FROM STAY S
WHERE YEAR(S.DATE) = 2011
GROUP BY S.ID_STAY) STAYHELPER
WHERE YEAR(S.DATE) = 2011
GROUP BY R.ID_ROOM, R.ID_ROOM_TYPE, T.DESCRIPTION
HAVING SUM(S.DAYS_QUANT) >= ALL STAYHELPER.TOTALDAYS