【问题标题】:Simplify query from select in select to use join在选择中简化查询以使用连接
【发布时间】:2020-04-01 16:31:13
【问题描述】:

我有两张这样的表:

Room
-----------------
id

和

Reservation
-----------------
id
room_id
check_in
check_out

我的目标是在特定的入住和退房期间获得所有没有预订的房间。

到目前为止,我已经设法构建这样的查询:

select * from room
where room.id not in (
select room2.id from room as room2
inner join reservation r on room2.id = r.room_id
where r.check_in > '2020-04-19' and r.check_out < '2020-04-25');

但我相信必须有一个更优化的方法来做到这一点,使用左连接。

我怎样才能构建一个等效的查询,只使用连接?

【问题讨论】:

    标签: mysql sql join left-join


    【解决方案1】:

    您可以使用 LEFT JOIN 过滤掉所有匹配的行:

    select rm.* 
    from room rm left join reservation rs
    on rs.room_id = rm.room_id and rs.check_in > '2020-04-19' and rs.check_out < '2020-04-25'
    where rs.room_id is null
    

    如您所见,所有条件都必须放在ON 子句中。

    【讨论】:

      【解决方案2】:

      我建议not exists:

      select r.*
      from room r
      where not exists (select 1
                        from reservation res
                        where r.id = res.room_id and
                              res.check_in > '2020-04-19' and
                              res.check_out < '2020-04-25'
                       );
      

      请注意,子查询中不需要join(在您的版本中也不需要,但我强烈反对not in 使用子查询,因为null 值的处理方式)。

      在性能方面,这应该比大多数数据库中的left join 更好或相当。它可以利用reservations(room_id, check_in, check_out) 上的索引。

      【讨论】:

        【解决方案3】:

        您的not in 方法不需要join,可以这样表达。 仅当您确定预订表中的相关列没有任何空值时才使用此选项。

        select * 
        from room
        where id not in (select room_id 
                          from reservation
                          where check_in > '2020-04-19' and check_out < '2020-04-25');
        

        如果你坚持使用join

        select t1.*
        from room t1
        inner join (select distinct room_id 
                    from reservation 
                    where check_in <= '2020-04-19' and check_out >= '2020-04-25') t2     
        on t1.id=t2.room_id
        

        【讨论】:

        • 我认为,鉴于标题“从选择中的选择简化查询以使用连接”,OP 希望仅使用连接来解决此问题。
        • XY 问题在 Stackoverflow 上并不少见。我可能是错的,但我认为 OP 想简化他的查询,并且可能认为加入是要走的路。如果您没有注意到,我确实添加了一种使用连接的方法。
        猜你喜欢
        • 1970-01-01
        • 2014-09-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-16
        相关资源
        最近更新 更多