【问题标题】:Total number of arrivals and average length of stay by hotel name and month按酒店名称和月份划分的到达总人数和平均停留时间
【发布时间】:2016-06-17 05:40:35
【问题描述】:

我正在尝试编写一个 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)

编辑:

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

【问题讨论】:

  • 研究使用GROUP BY 和聚合函数(如COUNTAVG)。
  • 如果CheckinDate 是 2016-05-31 而NumberofNights 是 2 怎么办?
  • 好吧,您无法准确预测,因为入住日期可能在月底,而且入住的晚数足以进入下个月。那你会怎么做?
  • 对不起,好点子!就“月份”而言,我严格按照入住日期对应的月份,而不是退房日期。
  • 给我们一些数据,进行测试。这会很有帮助。

标签: sql-server


【解决方案1】:
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)

而“魔法”就在这里

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 as decimal(22,6)) 因为如果 NumberofNights 是一个 int (我假设是这样),avg 也会返回一个 int 所以对于 3 次到达和 10 晚它会返回 3 不3.333333。

希望对你有帮助!

【讨论】:

  • 投了赞成票。没有时间自己纠正它。好同事
  • 谢谢,CiucaS!这个好像真的很近啊!唯一不能正常工作的是“TotalArrivals”。 COUNT(*) 没有给我正确的总数。我基本上是按酒店名称和月份查找预订总数。我尝试了 COUNT(re.ReservationID),但这似乎也不起作用。有什么想法吗?
  • @amaidie90 发布一些示例数据,以便我可以使用。因为理论上这应该可行。
【解决方案2】:

请检查以下 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

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

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

我必须将逗留天数乘以 1.0 才能得到十进制的平均值。 在最后一步中,我在整数部分之后将小数转换为 2 点。

希望对你有帮助,

【讨论】:

    【解决方案3】:

    当您在选择语句(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
    

    通过添加“月份”列,您可以进一步分解聚合。现在数据将返回按月细分的酒店总人数和平均停留时间。

    【讨论】:

      猜你喜欢
      • 2016-10-19
      • 1970-01-01
      • 2020-07-13
      • 1970-01-01
      • 2016-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-08
      相关资源
      最近更新 更多