我对这个有一点精神障碍。
我有酒店房间的预订系统,它包含一个表格
BookingRoomLink
BookingId(FK)
RoomId(FK)
START_DATE
END_DATE
我想查询数据以提取每个月的入住率。 我可以手动完成这个(即过去一个月做这样的事情)。
SELECT BookingRoomLink.Start_Date,
BookingRoomLink.End_Date,
DATEDIFF("d", BookingRoomLink.Start_Date, BookingRoomLink.End_Date) as RoomNights
FROM BookingRoomLink
WHERE BookingRoomLink.Start_Date >= dateadd(m, -1, getdate())
AND BookingRoomLink.End_Date <= GETDATE()
然后我可以对结果或类似情况进行计数,这会给我“使用”房间的夜晚,并在一个月内的房间晚上减去这个。
EG。 10个房间 x每月30天=可能有300个房晚。使用了150(来自查询的结果)= 50%的占用率。
问题
我想将其自动化为存储过程。
是否有可能将这个分组为特定年份的几个月?
我如何确保适合处理一个月边界的预订?
答案 0 :(得分:3)
如果您需要经常这样做,您可以将这些月份和年份部分作为持久计算列添加到您的表中,并为它们添加索引:
ALTER TABLE dbo.BookingRoomLink
ADD StartMonth AS MONTH(Start_Date) PERSISTED
ALTER TABLE dbo.BookingRoomLink
ADD StartYear AS Year(Start_Date) PERSISTED
ALTER TABLE dbo.BookingRoomLink
ADD EndMonth AS MONTH(End_Date) PERSISTED
ALTER TABLE dbo.BookingRoomLink
ADD EndYear AS Year(End_Date) PERSISTED
您现在可以选择这些新的计算列,在WHERE子句中使用它们,按这些列使用GROUP - 它们将始终基于Start_Date和End_Date进行更新 - 每次访问它们时都不会计算它们 - &GT;比在所有查询中使用DATEPART
快得多!
答案 1 :(得分:3)
WITH (
SELECT 0
UNION ALL
SELECT m + 1
FROM mon
WHERE m < 11
),
yr (y) AS
(
SELECT CAST('1990-01-01' AS DATETIME)
UNION ALL
SELECT DATEADD(year, 1, y)
FROM yr
WHERE y <= GETDATE()
),
dates (smy, emy) AS
(
SELECT DATEADD(month, m, y), DATEADD(month, m + 1, y)
FROM yr
CROSS JOIN
mon
),
diffs (smy, emy, days) AS
(
SELECT smy, emy, DATEDIFF(day, smy, emy)
FROM dates
)
SELECT smy,
roomId,
CAST(SUM(DATEDIFF(day,
CASE WHEN start_date < smy THEN smy ELSE start_date END,
CASE WHEN end_date > emy THEN emy ELSE end_date END
)) AS FLOAT) / days
FROM diffs
JOIN bookings
ON start_date < emy
AND end_date >= smy
GROUP BY
roomId, smy, emy, days
答案 2 :(得分:2)
您可以将日期“舍入”到该月的第一天,然后再将GROUP BY打开。与使用DatePart类似,但您仍然有一个有效的日期,因此您可以在执行分组之前或之后在WHERE子句中使用日期范围。
SELECT [Date] = DATEADD(Month, DATEDIFF(Month, 0, Start_Date), 0), -- 1st of the month [Bookings] = COUNT(*) FROM BookingRoomLink GROUP BY DATEADD(Month, DATEDIFF(Month, 0, Start_Date), 0) ORDER BY [Date]
答案 3 :(得分:0)
您可以使用DATEPART功能获取月号和分组号。
答案 4 :(得分:0)
如果您可以向表中添加计算列,请将其值设置为您要使用的月份。我肯定会选择“与行存储”而不是每次计算。
至于跨越几个月,您必须决定如何对其进行建模。如果您预订了3个月,该怎么办? 4? 12?更?
至于月份,您可以尝试像200911这样的6位数值,这样您就可以轻松地对它们进行排序,但将它们保存在整数字段中。如果计算了这个值,那么任何人都无法使用它。
答案 5 :(得分:0)
尝试:
Select DateName(month, start_Date) +
DateName(Year, Start_Date) as MonthName,
Sum(DateDiff(Day, Start_Date,
Case DateDiff(Month, Start_Date, End_Date)
When 0 Then End_Date
Else DateAdd(day, -day(Start_Date),
DateAdd(day, DateDiff(day, 0, Start_Date), 0)) Bookings
From BookingRoomLink
Group By DateName(month, start_Date) + DateName(Year, Start_Date)