按酒店名称和月份的总人数和平均逗留时间

时间:2016-06-17 05:40:36

标签: sql-server

我正在尝试提供一个SQL Server脚本,该脚本按酒店名称和月份显示到达总数和平均小数长度。任何帮助将不胜感激。

这是我正在寻找的输出类型:

HotelName          Month     TotalArrivals     AvgLengthofStay
==============================================================
Algonquin Hotel    June      300               4.25
Algonquin Hotel    July      375               3.65
The Four Seasons   June      485               4.45    
The Four Seasons   July      445               4.10
The Ritz-Carlton   June      ...               ...

以下是一些相关的表信息:

HOTEL:

HotelID (PK), HotelName, HotelAddress, HotelCity, HotelState, HotelPostalCode

RESERVATION:

ReservationID (PK), GuestID, RoomID (FK), CheckinDate, NumberofNights

ROOM (Only needed for table joins):

RoomID (PK), HotelID (FK)

编辑:

就“月”而言,我严格按照与入住日期相对应的月份,而不是退房日期。

3 个答案:

答案 0 :(得分:2)

CREATE TABLE #Hotels 
( HotelID int, HotelName varchar(10), HotelAddress  varchar(10), HotelCity  varchar(10), HotelState  varchar(10), HotelPostalCode  varchar(10))

CREATE TABLE #Reservation 
(
 ReservationID int, GuestID int, RoomID int, CheckinDate datetime, NumberofNights int
)

CREATE TABLE #Room
(
 RoomID int, HotelID int

)


INSERT INTO #Hotels (HotelID,HotelName) VALUES (1,'A')
INSERT INTO #Hotels (HotelID,HotelName) VALUES (2,'B')


GO


INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (1,1,1,'2016-01-05',5)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (2,2,1,'2016-08-05',3)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (3,3,1,'2016-06-05',2)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (4,1,1,'2016-01-12',1)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (5,2,1,'2016-08-18',8)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (6,3,1,'2016-06-30',7)





INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (1,1,2,'2016-02-01',5)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (2,2,2,'2016-02-06',3)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (3,3,2,'2016-02-09',2)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (4,1,2,'2016-04-03',1)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (5,2,2,'2016-04-07',8)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (6,3,2,'2016-04-05',7)


INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (1,1,3,'2016-07-01',15)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (2,2,3,'2016-11-06',2)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (3,3,3,'2016-11-09',9)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (4,1,3,'2016-12-03',8)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (5,2,3,'2016-06-07',10)
INSERT INTO #Reservation (ReservationID,GuestID,RoomID,CheckinDate,NumberofNights) 
VALUES (6,3,3,'2016-04-05',2)



INSERT INTO #Room VALUES (1,1)
INSERT INTO #Room VALUES (2,1)
INSERT INTO #Room VALUES (3,2)

和#34;魔法"在这里

SELECT HotelName, MONTH(re.CheckinDate) as Month, COUNT(*) as TotalArrivals, AVG(CAST(re.NumberofNights  as decimal(22,6) )) AS Avg
FROM #Hotels h 
join #Room r on r.HotelID = h.HotelID
join #Reservation re on re.RoomID = r.RoomID
GROUP BY h.HotelID, HotelName, MONTH(re.CheckinDate)

您需要做的是使用一个选择,并按HotelID和MONTH(re.CheckinDate)进行分组,这将为您提供一个月的基行(对于每个酒店,您将获得12行)。使用COUNT(*)将获得特定酒店一个月的所有记录,这是到达的总数量,使用Avg(NumberofNights)将获得平均夜数。

我也使用CASt(re.NumberofNights为十进制(22,6)),因为如果NumberofNights是一个int(我假设是这样),avg也将返回一个int,所以对于3个到达而10个晚上它将返回3而不是3.333333。

希望它有所帮助!

答案 1 :(得分:1)

请检查以下SQL Select语句

;with cte as (
select 
    h.HotelID,
    h.HotelName,
    r.ReservationID,
    DATENAME(mm,r.CheckinDate) as [month],
    r.NumberofNights * 1.0 as NumberofNights
from hotel h
inner join ROOM o on o.HotelID = h.HotelID
left join RESERVATION r on r.RoomID = o.RoomID and r.CheckinDate between '20160101' and '20161231'
)
select distinct
    HotelName,
    [month],
    COUNT(ReservationID) over (partition by HotelID, [month]) TotalArrivals,
    cast ( AVG(NumberofNights) over (partition by HotelID, [month]) as decimal(10,2))  AvgLengthofStay
from cte

我假设您熟悉SQL CTE (Common Table Expression)作为T-SQL开发人员

事实上,对于上面的Select语句,重要的是applying OVER and PARTITION BY clause to SQL mathematical functions,如SUM(),COUNT(),AVG()等。

我不得不将停留天数的长度乘以1.0得到十进制的平均值。 在最后一步中,我将小数转换为整数部分后的2个点。

我希望它可以帮助您解决问题,

答案 2 :(得分:0)

在select语句(SUM,AVG,COUNT等)中使用聚合函数时,需要确保按任何非聚合列对语句进行分组。选中的每个非聚合列都会将聚合列细分为更详细的信息。

SELECT HotelName,
       SUM(TotalArrivals) AS TotalArrivals,
       AVG(AvgLengthofStay) AS AvgLengthofStay
FROM dbo.Table
GROUP BY HotelName

此声明将为您提供自您的餐桌生命开始以来每间酒店的总入住人数和整体平均逗留时间。

SELECT HotelName,
       Month,
       SUM(TotalArrivals) AS TotalArrivals,
       AVG(AvgLengthofStay) AS AvgLengthofStay
FROM dbo.Table
GROUP BY HotelName, Month

通过添加Month列,可以进一步细分聚合。现在,数据将返回总入境人数和酒店的平均逗留时间,按月分类。