有没有其他替代方法可以编写此t-sql查询?

时间:2019-08-03 13:31:56

标签: sql sql-server tsql

我有以下3张桌子:

DB Diagram


对于每辆车,我需要可视化有关最近(最近)预订的数据:

  • 汽车模型(Model);
  • 预订汽车的用户(用户名);
  • 保留时(ReservedOn);
  • 返回时(ReservedUntil)。

如果没有给定汽车的预订,我只需要显示汽车型号。其他字段必须为空。


我写了以下查询:

SELECT 
  Reservations.CarId, 
  res.MostRecent, 
  Reservations.UserId, 
  Reservations.ReservedOn, 
  Reservations.ReservedUntil 
FROM 
  Reservations 
  JOIN (
    Select 
      Reservations.CarId, 
      MAX(Reservations.ReservedOn) AS 'MostRecent' 
    FROM 
      Reservations 
    GROUP BY 
      Reservations.CarId
  ) AS res ON res.carId = Reservations.CarId 
  AND res.MostRecent = Reservations.ReservedOn

Expected something like this

这第一个有效,但是我被困住以获得所需的结果。如何编写完整的查询?

2 个答案:

答案 0 :(得分:0)

使用not exists

select r.* from reservations r
where not exists (
  select 1 from reservations  
  where carid = r.carid and reservedon > r.reservedon
)

您可以使用上面的代码创建一个CTE并将其连接到其他表:

with cte as (
    select r.* from reservations r
    where not exists (
      select 1 from reservations  
      where carid = r.carid and reservedon > r.reservedon
    )
)
select c.carid, c.model, u.username, cte.reservedon, cte.reserveduntil
from cars c
left join cte on c.carid = cte.carid 
left join users u on u.userid = cte.userid

如果您不想使用CTE:

select c.carid, c.model, u.username, t.reservedon, t.reserveduntil
from cars c
left join (
    select r.* from reservations r
    where not exists (
      select 1 from reservations  
      where carid = r.carid and reservedon > r.reservedon
    )
) t on c.carid = t.carid 
left join users u on u.userid = t.userid

答案 1 :(得分:0)

这似乎是经典的每组前n个问题。

一种实现方法是使用OUTER APPLY。它是一个相关的子查询(横向联接),它为Cars表中的每一行返回最新的Reservation。如果某辆车不存在这样的预订,则将为空。

如果在Reservations上为(CarID, ReservedOn DESC)表创建索引,则此查询应比自联接更有效。

SELECT
    Cars.CarID
    ,Cars.Model
    ,A.ReservedOn
    ,A.ReservedUntil
    ,A.UserName
FROM
    Cars
    OUTER APPLY
    (
        SELECT TOP(1)
            Reservations.ReservedOn
            ,Reservations.ReservedUntil
            ,Users.UserName
        FROM
            Reservations
            INNER JOIN Users ON Users.UserId = Reservations.UserId
        WHERE
            Reservations.CarID = Cars.CarID
        ORDER BY
            Reservations.ReservedOn DESC
    ) AS A
;

有关此常见问题的其他方法,请参见Get top 1 row of each group

Retrieving n rows per group