質問

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

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

BookingroomLink
BookingID(FK)
Roomid(fk)
開始日
終了日

毎月、占有レベルを抽出するためにデータを照会したいと思います。私はこれを手動で行うことができました(つまり、このようなことをします)。

 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%の占有。

問題

idはこれをストアドプロシージャに自動化するのが好きです。

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

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

役に立ちましたか?

解決

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

他のヒント

これを頻繁に行う必要がある場合は、それらの月と年のパーツを永続化された計算列としてテーブルに追加して、それらにインデックスを置くことができます。

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

これらの新しい計算された列を選択し、句でそれらを使用することができます。それらの列によってグループをグループ化できます - そして、それらはstart_dateとend_dateに基づいて常に最新のものになります - それらにアクセスするたびに計算されません - >はるかに高速単に使用するよりも DATEPART すべてのクエリで!

日付を月の1日まで「締めくく」、それをグループ化することができます。 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]

使用できます datepart その数で月数とグループを取得する機能。

計算された列をテーブルに追加できる場合は、その価値を使用したい月にしてください。私は間違いなく「row with row with row」とコンピューティートを選択します。

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

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

試す:

 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)
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top