【问题标题】:How do I get a value from the next record with a WHERE condition in SQL?如何从 SQL 中带有 WHERE 条件的下一条记录中获取值?
【发布时间】:2018-08-29 09:16:12
【问题描述】:

我使用 Management Studio 创建了一个 SQL 视图。该视图将几个表连接在一起,并由我的 MVC 应用程序访问。这些表格与汽车租赁有关。一个表保存汽车详细信息,而另一个表保存预订信息,这些信息使用视图连接。

视图正常工作,但我被要求添加一列,显示汽车的下一个即时预订。这意味着我需要一个列来显示汽车 ID 匹配的下一个预订开始日期。

表格:汽车

  • [ID]
  • [注册]
  • [制作]
  • [型号]

表格:预订

  • [ID]
  • [预订开始日期]
  • [预订结束日期]
  • [车牌号]

查看:CarBookings

SELECT  [C].[Id],
        [C].[Registration],
        [C].[Make],
        [C].[Model],
        [B].[BookingStartDate],
        [B].[BookingEndDate]

  FROM [Cars] AS C INNER JOIN [Bookings] AS B ON C.Id = B.CarId

如何在我的视图中添加一列以显示汽车的下一次预订?任何帮助表示赞赏。

【问题讨论】:

  • 我没有看到任何逻辑可用于确定显示哪个第一个预订。您当前的视图将显示给定汽车的所有预订。一些示例数据在这里会有所帮助。
  • 您能否详细说明“下一次立即预订”?这个逻辑是如何工作的?那存储在哪里?在这种情况下,您有哪些可用数据?您当前的 sql 应该只检索您的汽车和预订之间的所有相关实例,这意味着默认情况下您还将获得“下一个立即预订”,假设它存储在预订表中?
  • 从问题看来,您似乎需要在当前日期时间或之后进行第一次预订?如果是这样,那么您可以使用 TOP or a LIMIT 和 order by。但该语法相当依赖于数据库。所以你可能想为你需要的数据库类型添加一个标签。
  • 您只想显示汽车信息和下一次预订吗? (如前所述,您当前的查询当前显示所有预订,旧的和新的)

标签: sql model-view-controller


【解决方案1】:

使用LEAD()(sql server 2012 起)

select c.*, b.BookingStartDate, b.BookingEndDate,
       lead(bookingstartdate) over (partition by carid order by BookingStartDate) as nextbooking
from cars c
inner join bookings b
on c.id = b.carid

【讨论】:

  • 我喜欢使用LEAD(如果可用)的想法,但我认为您需要以某种方式限制您的查询以仅返回最新的预订记录(它当前返回所有内容)。
  • 我也这么认为,只是在b.BookingEndDate 后面漏了逗号,你的意思是BookingEndDate 而不是date
  • @TimBiegeleisen 问题不清楚,所以提供整体观点
【解决方案2】:

正如蒂姆在 cmets 中提到的,您的查询已经为您提供了所有预订,但如果您需要在另一列中,那么您可能需要 lead() 吗?

SELECT  C.Id,
B.BookingStartDate,
B.BookingEndDate,
lead(BookingStartDate) over(partition by C.Id order by B.BookingEndDate) nextdt
FROM Cars AS C INNER JOIN Bookings AS B ON C.Id = B.CarId

【讨论】:

    【解决方案3】:

    这是一个应该生成您想要的结果的查询。在 CTE 中,我使用数据透视查询来显示每个 CarId 的最近和第二最近的预订记录。然后,我们以您已经在做的类似方式将此 CTE 加入到 Car 表中。

    WITH cte AS (
        SELECT
            CarId,
            MAX(CASE WHEN rn = 1 THEN BookingStartDate END) AS BookingStartDate,
            MAX(CASE WHEN rn = 1 THEN BookingEndDate   END) AS BookingEndDate,
            MAX(CASE WHEN rn = 2 THEN BookingStartDate END) AS NextBookingStartDate,
            MAX(CASE WHEN rn = 2 THEN BookingEndDate   END) AS NextBookingEndDate
        FROM
        (
            SELECT CarId, BookingStartDate, BookingEndDate,
                ROW_NUMBER() OVER (PARTITION BY CarId ORDER BY BookingStartDate DESC) rn
            FROM Bookings
        ) t
        WHERE rn <= 2
        GROUP BY CarId
    )
    
    SELECT
        c.Id,
        c.Registration,
        c.Make,
        c.Model,
        b.BookingStartDate,
        b.BookingEndDate,
        b.NextBookingStartDate,
        b.NextBookingEndDate
    FROM Cars c
    INNER JOIN cte b
        ON c.Id = b.CarId;
    

    【讨论】:

      【解决方案4】:

      如果现有视图执行您想要的操作(即所有汽车和预订的组合,但由于您使用内部联接而没有预订的汽车除外), 并且您只想投影我假设引用当前日期时间的“下一个”订单,

      您可以将左联接添加到查询中,该查询会提取每辆车的“下一个”预订,并创建一个列,当它与下一条记录匹配时对其进行调节。

      左连接逻辑:

      1. 获取每辆车未来的所有预订(即 where 过滤器)
      2. 下一个(最少预订时间)。
      3. 加入 - 在预订日期和 carId(现在如果有两个相同的 每辆车的预订,您将获得两者作为下一场比赛,因为加入 条件将适用于两者)。

        select 
        a.* , 
        b.* ,
        case when c.carId is not null then 1 else 0 end as IsNext
        from cars a
        inner join bookings b
            on a.id = b.carid
        left join (select carid , min(bookingStartDate) bookingStartDate from bookings where bookingStartDate > now() group by carid) c
            on b.carId = c.carId
            and b.bookingStartDate = c.bookingStartDate
        

      【讨论】:

      • 评论:答案是 postgres 语法,因为您没有指定您使用的数据库。如果是 sql server - 将 now() 替换为 GETDATE()
      【解决方案5】:

      下面的查询将给出特定汽车的即将到来的所有预订。如果您只想要下一个,那么您应该使用 Row_number。

      SELECT  [C].[Id],
              [C].[Registration],
              [C].[Make],
              [C].[Model],
              [B].[BookingStartDate],
              [B].[BookingEndDate]
      
        FROM [Cars] AS C 
        INNER JOIN [Bookings] AS B ON C.Id = B.CarId
        WHERE [B].[BookingStartDate] >= GETDATE()
        ORDER BY [B].[BookingStartDate]
      

      【讨论】:

        猜你喜欢
        • 2011-10-21
        • 2013-08-02
        • 2020-01-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-17
        • 1970-01-01
        相关资源
        最近更新 更多