首页 > 解决方案 > 如何根据 SQL Server 查询中的日期返回下一个后续记录?

问题描述

作为我的船舶租赁数据库的一部分,我有一个视图,它返回有关我们拥有的船舶及其固定承诺的一系列信息。在我们的系统中,固定装置上的任何船只都将该承诺标记为“实时”,并且该船只在停租日期之后的任何固定装置承诺都将标记为“后续”(实时和后续标记由用户在前端)。

问题

一艘船可以有多个 FollowOn 承诺,因此我需要找到一种方法,在当前 Live 承诺的停租日期之后仅返回标记为 FollowOn 的下一个承诺。

查询(到目前为止)

SELECT        

uve.[Id], 
uve.[ViewId], 
uve.[VesselId], 
ve.[Name],

/***********************  
    #Fixture (Current)
***********************/ 
CAST((CASE WHEN fix1.[Id] IS NULL THEN 0 ELSE fix1.[Id] END) AS INT) AS [FixtureId], 
fix1.[Date], 
fix1.[FirmUntil], 
fix1.[Charterer],
ch1.[ChartererName],

/***********************  
    #Fixture (Next)
***********************/ 
fix2.FollowOn,
fix2.Id AS NextFixtureId, 
fix2.[Date] AS NextOnhire,
CAST((CASE WHEN fix2.FollowOn IS NULL THEN 0 ELSE fix2.FollowOn END) AS BIT) AS FollowOn, 
fix2.[FirmUntil] AS NextOffhire, 
ch2.ChartererName AS NextChartererName,
CAST((CASE WHEN fix1.[Live] IS NULL THEN 0 ELSE fix1.[Live] END) AS BIT) AS Live

FROM UserVessels AS uve 
LEFT JOIN Vessel AS ve ON ve.Id = uve.VesselId 
LEFT JOIN VesselTypes AS vt ON vt.[Id] = ve.[Type] 

LEFT JOIN (SELECT  [Id], [Date], [FirmUntil], [PeriodAmount], [PeriodFrequency], [Charterer], [Port], [Live],[FollowOn], [Broker], [WorkRole], [VesselId]
            FROM Fixture
            WHERE Live = '1' AND FollowOn = '0') AS fix1 ON fix1.[VesselId] = ve.Id

LEFT JOIN (SELECT [Id],[Date],[Live],[FirmUntil],[FollowOn], [Charterer], [Port], [WorkRole], [VesselId]
            FROM Fixture AS f2
            WHERE f2.[FollowOn] = '1') AS fix2 on fix2.[VesselId] = ve.Id
            

LEFT JOIN Charterer AS ch1 ON ch1.Id = fix1.Charterer 
LEFT JOIN Charterer AS ch2 ON ch2.Id = fix2.Charterer

如您所见,我想要实现的繁重工作发生在我有一个查看 FollowOn 标志的子查询的连接中。这并不理想,因为如果有不止一个带有后续的夹具,那么你会得到很多行。我只需要在“fix1”停租后立即进行下一个后续操作,这样我就可以将每艘船保持为一排,并且想知道如何实现这一目标?

标签: sqlsql-server

解决方案


因此,如果您有一个关于固定装置的所有后续列表,正如评论中提到的,您可以使用 row_number 窗口函数来获取下一个:

LEFT JOIN (SELECT [Id],[Date],[Live],[FirmUntil],[FollowOn], [Charterer], [Port], [WorkRole], [VesselId], ROW_NUMBER() OVER (PARTITION BY VesselId ORDER BY Date) [RNum]
            FROM Fixture AS f2
            WHERE f2.[FollowOn] = '1') AS fix2 on fix2.[VesselId] = ve.Id AND fix2.RNum = 1

但是外部应用可能会更快。你需要测试它。


推荐阅读