2

私はこれに少し精神的なブロックを持っています。

ホテルの部屋の予約システムを取得しましたが、テーブルが含まれています。

BookingRoomLink BookingId
(FK)
RoomId(FK)
Start_Date
End_Date

データをクエリして、各月の占有レベルを抽出したいと思います。私はこれを手動で行うことができます(つまり、過去1か月間はこのようなことを行います)。

 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()

次に、結果などをカウントして、「使用済み」の部屋の夜を計算し、これを1か月に利用可能な部屋の夜から差し引くことができます。

例えば。10部屋x月の30日=利用可能な300の可能な部屋の夜。150使用(クエリの結果)= 50%の占有率。

問題

これをストアドプロシージャに自動化したいと思います。

これを特定の年の月にグループ化することは可能ですか?

月の境界と重なる予約が適切に処理されるようにするにはどうすればよいですか?

4

6 に答える 6

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に基づいて常に最新の状態になります。これらの列にアクセスするたびに計算されるわけではなく、はるかに高速です。DATEPARTすべてのクエリで使用するだけではありません。

于 2009-11-16T18:19:16.447 に答える
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
于 2009-11-16T18:19:53.217 に答える
2

日付をその月の1日に「丸め」てから、その上でGROUPBYを実行できます。DatePartの使用と似ていますが、まだ有効な日付があるため、グループ化を実行する前または後に、WHERE句で日付範囲を使用できます。

SELECT [Date] = DATEADD(Month、DATEDIFF(Month、0、Start_Date)、0)、-月の1日
       [予約]=COUNT(*)
BookingRoomLinkから
GROUP BY DATEADD(Month、DATEDIFF(Month、0、Start_Date)、0)
注文者[日付]
于 2009-11-16T18:33:35.887 に答える
0

DATEPART関数を使用して、月番号を取得し、その番号でグループ化できます。

于 2009-11-16T18:11:59.597 に答える
0

計算列をテーブルに追加できる場合は、その値を使用する月にします。私は間違いなく「行のあるストア」と毎回の計算を選択します。

何ヶ月にもわたって、それをどのようにモデル化するかを決める必要があります。3か月間の予約がある場合はどうなりますか?4?12?もっと?

月については、200911のような6桁の値を試して、簡単に並べ替えることができますが、整数フィールドに保持することができます。値が計算された場合、誰もそれを使用することはできません。

于 2009-11-16T18:16:18.590 に答える
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)
于 2009-11-16T18:32:36.060 に答える