我有两个表,我正在尝试使用T-SQL聚合数据。 架构:
CREATE TABLE rooms (
room_id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
room_name varchar(50)
);
CREATE TABLE bookings (
id int NOT NULL,
account_id int,
room_id int,
booking_timestamp datetime,
);
数据:
INSERT INTO rooms (room_id, room_name)
VALUES ('1', 'Suite A'),
('2', 'Suite B'),
('3', 'Suite C'),
('4', 'Suite D'),
('5', 'Suite X');
INSERT INTO bookings (id, account_id, room_id, booking_timestamp)
VALUES ('1', '123', '1', '2018-12-21 10:00:00'),
('1', '123', '1'), '2018-12-21 10:00:00',
('2', '123', '1', '2018-12-20 10:00:00'),
('3', '123', '1', '2018-12-19 10:00:00'),
('4', '123', '1', '2018-12-18 10:00:00'),
('5', '123', '2', '2018-12-17 10:00:00'),
('6', '123', '3', '2018-12-16 10:00:00'),
('7', '123', '4', '2018-12-15 10:00:00'),
('8', '123', '4', '2018-12-14 10:00:00'),
('9', '123', '5', '2018-12-14 10:00:00'),
('10', '123', '1', '2018-12-13 10:00:00'),
('11', '124', '4', '2018-12-21 10:00:00'),
('12', '124', '5', '2018-12-22 10:00:00'),
('13', '124', '1', '2018-12-23 10:00:00'),
('14', '124', '1', '2018-12-24 10:00:00');
查询:
SELECT ar.room_id, ar.cnt as number_of_bookings
FROM (SELECT room_id, count(*) AS cnt,
row_number() over (
partition by room_id order by count(*) desc,
max(booking_timestamp) desc) AS seqnum
FROM bookings
WHERE booking_timestamp >= '2018-01-01'
GROUP BY room_id, id
) ar
WHERE seqnum = 1
现在请注意,在我的数据中预订表的ID不是唯一的,可能有多个ID相同的实例(只是日期不同)。
我正在使用的查询似乎也不能产生由id
分组的I组的正确结果。当我仅使用room_id
时,它们可以正常工作。
有人可以告诉我我在做什么错吗?
编辑:所需结果
account_id | most booked room | count 123 | Suite A | 5 124 | Suite A | 2
答案 0 :(得分:1)
您所期望的结果使我相信您在房间里预订最多的帐户。这意味着您必须按帐户而不是房间进行分区。
SELECT x.account_id,
r.room_name "most booked room",
x.count
FROM (SELECT b.account_id,
b.room_id,
count(*) count,
row_number() OVER (PARTITION BY b.account_id
ORDER BY count(*) DESC) rownumber
FROM bookings b
WHERE b.booking_timestamp >= '2018-01-01'
GROUP BY b.account_id,
b.room_id) x
LEFT JOIN rooms r
ON r.room_id = x.room_id
WHERE x.rownumber = 1;
db<>fiddle(注意:这是MySQL 8.0,因为AUTO_INCREMENT
是MySQL,而不是T-SQL标记所暗示的SQL Server。但是查询也适用于SQL Server。)
答案 1 :(得分:0)
分而治之的长途之路
;WITH cte AS
(
select account_id, r.room_name, count(*) as cnt
from bookings b
inner join rooms r on b.room_id = r.room_id
group by account_id, r.room_name
)
,cte2 AS
(
select *,
ROW_NUMBER() OVER(PARTITION BY account_id ORDER BY cnt DESC) rn
from cte
)
select account_id, room_name as most_booked_room, cnt as [count]
from cte2
where rn = 1
从您期望的结果来看,我假设您想查看哪个帐户使用的房间最多。因此,您需要按account_id,room_id将所有数字分组。但是,在partition by子句中,仅由于要在单个帐户中而不是单个帐户和单个房间中对数字进行排名,才需要按account_id对其进行分区。
原始查询的外观如下:
select account_id, room_id, cnt from
(
SELECT account_id, room_id, count(*) AS cnt,
row_number() over (partition by account_id order by count(*) desc, max(booking_timestamp) desc) AS seqnum
FROM bookings
WHERE booking_timestamp >= '2018-01-01'
GROUP BY account_id, room_id
) a
WHERE seqnum = 1
但是我更喜欢分而治之,是的,它的类型更多,但如果将来需要一些调整,它也更具可读性和可维护性。
答案 2 :(得分:0)
请尝试一下。
----drop table rooms drop table bookings
CREATE TABLE rooms (
room_id int NOT NULL ,
room_name varchar(50)
);
CREATE TABLE bookings (
id int NOT NULL,
account_id int,
room_id int,
booking_timestamp datetime,
);
INSERT INTO rooms (room_id, room_name)
VALUES ('1', 'Suite A'),
('2', 'Suite B'),
('3', 'Suite C'),
('4', 'Suite D'),
('5', 'Suite X');
INSERT INTO bookings (id, account_id, room_id, booking_timestamp)
VALUES ('1', '123', '1', '2018-12-21 10:00:00'),
('1', '123', '1', '2018-12-21 10:00:00'),
('2', '123', '1', '2018-12-20 10:00:00'),
('3', '123', '1', '2018-12-19 10:00:00'),
('4', '123', '1', '2018-12-18 10:00:00'),
('5', '123', '2', '2018-12-17 10:00:00'),
('6', '123', '3', '2018-12-16 10:00:00'),
('7', '123', '4', '2018-12-15 10:00:00'),
('8', '123', '4', '2018-12-14 10:00:00'),
('9', '123', '5', '2018-12-14 10:00:00'),
('10', '123', '1', '2018-12-13 10:00:00'),
('11', '124', '4', '2018-12-21 10:00:00'),
('12', '124', '5', '2018-12-22 10:00:00'),
('13', '124', '1', '2018-12-23 10:00:00'),
('14', '124', '1', '2018-12-24 10:00:00');
;with cte as (
select a.room_id,a.room_name,b.account_id,
count(*)over(partition by b.account_id,b.room_id) as count ,
row_number()over(partition by b.account_id order by (select 1)) as rn
from rooms a
join bookings b on a.room_id=b.room_id)
select account_id,room_name,count from cte where rn=1
/*
account_id room_name count
----------- -------------------------------------------------- -----------
123 Suite A 6
124 Suite A 2
*/
最好的问候
瑞秋