3

私が仕事をすることができない一見単純なクエリ...

2 つのテーブルの部屋と空室状況

Room         [id, title, beds]
Availability [room_id, date, bed_delta]

ルームには、利用可能なベッドの最大数が固定されています。可用性は、変更された期間Room.beds(アップまたはダウン) を表します。

特定の部屋と特定の開始日と期間について、利用可能なベッドを合計するクエリを作成しようとしています。

例えば:

  • ルーム1には通常2つのベッドがあります
  • 1時間、1ベッドが取られます
  • 期待される結果は 1

この日時範囲と重複する別の利用可能期間が追加され、ベッド数がさらに 1 減少した場合、予想される結果は 0 になります。

比較的単純なクエリのように感じます。

  • LEFT OUTER JOIN room_id の空室状況への Room
  • 日付による制約
  • Room.beds を選択 - sum(Availability.bed_delta)

すなわち

SELECT r.beds - coalesce(sum(a.bed_delta), 0) as beds_free
FROM room r
LEFT OUTER JOIN availability a ON (r.id = a.room_id)
WHERE date = '2012-01-01 09:00:00+01:00'
AND r.id = 2
GROUP BY r.id;

このクエリは、一致する行が にある場合にのみ返されavailabilityます。私が期待したのは、id == 2 の部屋の 1 つの行でした。

4

1 に答える 1

9

問題はあなたのWHERE条項のこの部分です:

WHERE date = '2012-01-01 09:00:00+01:00'

外部結合は、結合条件(ここではr.id = a.room_id)が失敗する行のみを「許可」します。句に課されている右側のテーブルの他の制約はWHERE、結果から行全体を除外する可能性があります。ええ、それはトリッキーです。

date解決策:制約を結合条件に移動します。

LEFT OUTER JOIN availability a ON (r.id = a.room_id AND date = '2012-01-01 09:00:00+01:00')

(はい、驚くべきことに、そこに任意の条件を設定できます。現在発見しているように、(外部結合の場合)これが必要になる場合があります!)

または、相関サブクエリを使用して、対象のAvailabilityレコードに一致するすべてのレコードの合計を見つけることもできますRoom

SELECT r.beds - coalesce((
    SELECT sum(a.bed_delta)
    FROM availability a
    WHERE a.room_id = r.id
    AND date = '2012-01-01 09:00:00+01:00'
), 0) as beds_free
FROM room r
WHERE r.id = 2;

サブクエリは、ed外部結合よりも理解しやすいと思いますGROUPが、YMMVです。

于 2012-08-08T15:10:24.877 に答える