3

一个看似简单的查询,我无法完成......

两张桌子的房间和可用性

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

一个房间有一个固定的最大可用床数。可用性描述Room.beds了修改(向上或向下)的时间段。

我正在尝试构建一个查询,对于给定的房间和给定的开始日期和持续时间,将汇总可用床位。

例如:

  • 房间 1 通常有 2 张床
  • 1小时,占用1张床
  • 预期结果为 1

如果添加与此日期时间范围重叠的另一个可用时间段并将床位进一步减少 1,则预期结果为 0。

感觉像是一个相对简单的查询:

  • LEFT OUTER JOIN Room to Availability on room_id
  • 按日期约束
  • 选择 Room.beds - sum(Availability.bed_delta)

IE

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 的房间只有一行。

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;

我发现子查询比外连接更容易理解GROUP,但是 YMMV。

于 2012-08-08T15:10:24.877 回答