Rob*_*wie 3 postgresql outer-join
一个看似简单的查询,我无法工作......
两个桌子的房间和可用性
Room [id, title, beds]
Availability [room_id, date, bed_delta]
Run Code Online (Sandbox Code Playgroud)
客房配有固定的最多床位数.可用性描述Room.beds修改期间(向上或向下).
我正在尝试构建一个查询,对于给定的房间和给定的开始日期和持续时间将总和可用的床.
例如:
如果添加了与此日期时间范围重叠的另一个可用时段并进一步将床减少1,则预期结果为0.
感觉就像一个相对简单的查询:
即
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;
Run Code Online (Sandbox Code Playgroud)
此查询仅在匹配的行中返回availability.我期望的是id为== 2的房间的单行.
问题是你的WHERE条款的这一部分:
WHERE date = '2012-01-01 09:00:00+01:00'
Run Code Online (Sandbox Code Playgroud)
外连接仅"允许" 连接条件(此处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')
Run Code Online (Sandbox Code Playgroud)
(是的,令人惊讶的是,你可以在那里坚持任意条件,正如你现在发现的那样,(对于外连接)这可能是必要的!)
或者,您可以使用相关子查询来查找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;
Run Code Online (Sandbox Code Playgroud)
我发现子查询比GROUPed外连接更容易理解,但是YMMV.