2

ベッド数の異なるホテルがたくさんあります。私は、特定の日に、各ホテルで何台のベッドが占有されているかを知る必要があります。

サンプルデータ:

 HOTEL      CHECK-IN     CHECK-OUT
   A       29.05.2010   30.05.2010
   A       28.05.2010   30.05.2010
   A       27.05.2010   29.05.2010
   B       18.08.2010   19.08.2010
   B       16.08.2010   20.08.2010
   B       15.08.2010   17.08.2010

中間結果:

HOTEL      DAY          OCCUPIED_BEDS
  A     27.05.2010           1      
  A     28.05.2010           2
  A     29.05.2010           3
  A     30.05.2010           2
  B     15.08.2010           1
  B     16.08.2010           2
  B     17.08.2010           2
  B     18.08.2010           2
  B     19.08.2010           2
  B     20.08.2010           1

最終結果:

 HOTEL     MAX_OCCUPATION  
   A            3
   B            2

同様の質問が前に尋ねられます。2つの日付の間の日付のリスト(Tom Kyteが示すように)を取得し、で毎日の容量を計算することを考えましたgroup by。問題は、私のテーブルが比較的大きいことです。このタスクを実行するためのより安価な方法があるのではないかと思います。

4

3 に答える 3

2

興味のある日を含む一時テーブルを作成します

create table #dates (dat datetime)
insert into #dates (dat) values ('20121116')
insert into #dates (dat) values ('20121115')
insert into #dates (dat) values ('20121114')
insert into #dates (dat) values ('20121113')

予約日ごとに1つが「生成」されるように、予約を日付と結合して中間結果を取得します

SELECT Hotel, d.dat, COUNT(*) from bookings b
INNER JOIN #dates d on d.dat BETWEEN b.checkin AND b.checkout
GROUP BY Hotel, d.dat 

最後にマックスを手に入れよう

SELECT Hotel, Max(OCCUPIED_BEDS) FROM IntermediateResult GROUP BY Hotel
于 2012-11-16T20:30:40.203 に答える
2

質問で概説したアプローチよりも優れたアプローチはないと思います。日テーブルを作成します(またはその場で生成します)。個人的には、年に一度更新されるものを横に置いておくのが好きです。

分析関数を理解している人は、おそらく内部/外部クエリなしでこれを行うことができますが、内部グループは外部のサブセットであるため、大きな違いはありません。

Select
  i.Hotel,
  Max(i.OccupiedBeds)
From (
  Select
    s.Hotel,
    d.DayID,
    Count(*) As OccupiedBeds
  From
    SampleData s
      Inner Join
    Days d
      -- might not need to +1 depending on business rules.
      -- I wouldn't count occupancy on the day I check out, if so get rid of it
      On d.DayID >= s.CheckIn And d.DayID < s.CheckOut + 1 
  Group By
    s.Hotel, 
    d.DayID
  ) i
Group By
  i.Hotel

少し遊んだ後、内部クエリなしで分析関数バージョンを機能させることができませんでした:

これで速度が本当に問題になる場合は、メインテーブルにトリガーがある中間テーブルを維持することを検討できます。

http://sqlfiddle.com/#!4/e58e7/24

于 2012-11-16T20:37:59.807 に答える
1

パフォーマンスの問題は、結合条件が等式に基づいていないため、ハッシュ結合が不可能になることです。ホテルと日のペアを持つテーブルhotel_dayがあると仮定すると、次のようなものを試してみます。

select ch_in.hotel, ch_in.day,
       (check_in_cnt - check_out_cnt) as occupancy_change
from   ( select d.hotel, d.day, count(s.hotel) as check_in_cnt
         from   hotel_days d,
                sample_data s
         where  s.hotel(+) = d.hotel
           and  s.check_in(+) = d.day
         group  by d.hotel, d.day
       ) ch_in,
       ( select d.hotel, d.day, count(s.hotel) as check_out_cnt
         from   hotel_days d,
                sample_data s
         where  s.hotel(+) = d.hotel
           and  s.check_out(+) = d.day
         group  by d.hotel, d.day
       ) ch_out
where  ch_out.hotel = ch_in.hotel
  and  ch_out.day = ch_in.day

トレードオフはダブルフルスキャンですが、それでもより高速に実行され、並列化される可能性があると思います。(sample_dataは、ホテル自体の数ではなく、主に予約の数が原因で大きいと思います。)出力は、特定の日の特定のホテルの占有率の変化ですが、これは、どちらの分析でも簡単に合計値にまとめることができます。関数または(おそらくより効率的に)一括収集を使用するPL/SQLプロシージャ。

于 2012-11-17T14:06:39.063 に答える