选择具有最长日期和其他条件的行

Posted

技术标签:

【中文标题】选择具有最长日期和其他条件的行【英文标题】:Select the row with the maximum date and other criteria 【发布时间】:2018-06-26 07:02:20 【问题描述】:

我知道以前有人问过这个问题,并且我查看了很多解决方案,但我无法调整任何解决方案来适应我的问题。 我想返回每个公司的行和具有最大日期的 complianceTypeID。

此查询显示我的数据。

    SELECT [ComplianceItemID]
      ,[CorporationID]
      ,[Date]
      ,[ComplianceTypeID]
  FROM [Compliance].[dbo].[ViewComplianceItem]
  Where CorporationID = '869'

返回这个结果

ComplianceItemID    CorporationID       Date        ComplianceTypeID
55761               869                 2018-06-20  1
56840               869                 2022-11-07  2
57919               869                 1900-01-01  3
58998               869                 1900-01-01  4
60077               869                 1900-01-01  5
61156               869                 1900-01-01  6
62235               869                 1900-01-01  7
63316               869                 2018-06-25  8
63322               869                 2018-06-26  1

我只想返回每个 ComplianceTypeID 中日期最高的行

我稍后将参数化查询而不是固定的 CoprorationID。

我希望看到返回 8 行,应排除第 1 行,因为还有另一个 ComplianceTypeID 1 具有较新的日期。

我已经尝试过了,但只返回了 5 行,日期均为 '1900-01-01'

SELECT
    VC1.ComplianceItemID, 
    VC1.CorporationID, 
    VC1.[Date], 
    VC1.ComplianceTypeID 
FROM ViewComplianceItem VC1
Left Join ViewComplianceItem VC2 
    On VC1.ComplianceTypeID = VC2.ComplianceTypeID
    AND VC1.[Date] > VC2.[Date]
Where VC2.[Date] is null 
AND VC1.CorporationID = '869'

结果

ComplianceItemID    CorporationID       Date        ComplianceTypeID
57919               869                 1900-01-01  3
58998               869                 1900-01-01  4
60077               869                 1900-01-01  5
61156               869                 1900-01-01  6
62235               869                 1900-01-01  7

似乎还有许多其他方法可以解决这个问题。 我只需要一个有效的 :) 我已经绞尽脑汁半天了,没有进步。

感谢您的帮助 大卫

【问题讨论】:

【参考方案1】:

这通常使用窗口函数来处理。

create procedure my proc (@corpID int)
as
begin

    ;WITH CTE AS(
    SELECT 
        [ComplianceItemID]
        ,[CorporationID]
        ,[Date]
        ,[ComplianceTypeID]
        ,RN = row_number() over (partition by ComplianceTypeID order by [Date] desc)
    FROM [Compliance].[dbo].[ViewComplianceItem]
    WHERE CorporationID = @corpID)

    SELECT 
        [ComplianceItemID]
        ,[CorporationID]
        ,[Date]
        ,[ComplianceTypeID]
    FROM CTE
    WHERE RN = 1
end

您也可以不进行参数化,或忽略 WHERE 子句,并将其添加到 PARTITION BY 以恢复您的逻辑,适用于每个公司。

WITH CTE AS(
SELECT 
    [ComplianceItemID]
    ,[CorporationID]
    ,[Date]
    ,[ComplianceTypeID]
    ,RN = row_number() over (partition by CorporationID, ComplianceTypeID order by [Date] desc)
FROM [Compliance].[dbo].[ViewComplianceItem])

SELECT 
    [ComplianceItemID]
    ,[CorporationID]
    ,[Date]
    ,[ComplianceTypeID]
FROM CTE
WHERE RN = 1

最后,这也可以使用派生表和MAX 聚合来处理:

SELECT 
    t1.[ComplianceItemID]
    ,t1.[CorporationID]
    ,t1.[Date]
    ,t1.[ComplianceTypeID]
FROM [Compliance].[dbo].[ViewComplianceItem] t1
INNER JOIN (SELECT CorporationID, ComplianceItemID, MAX([Date]) dt
            FROM [Compliance].[dbo].[ViewComplianceItem]
            GROUP BY CorporationID, ComplianceItemID) t2 on
            t2.CorporationID = t1.CorporationID 
            and t2.ComplianceItemID = t1.ComplianceItemID
            and t2.dt = t1.[Date]

【讨论】:

@scismon,感谢您的详细回复,使用派生表的第三个选项不起作用。它仍然返回所有 9 行。前两个示例有效,但它们引入了几个我不理解的新概念。如何参数化它以便我可以选择一个公司 ID? 我想我找到了让它发挥作用的方法。我用你的 sql 创建了一个视图。我应该能够创建一个从视图中读取数据的参数化查询。不是最优雅的解决方案,但我认为它会起作用。我不确定您是否建议我使用您的 sql 创建函数?明天我会对此进行测试,并在它起作用后将您的答案标记为正确:) 我进行了编辑,向您展示如何使用 proc 进行操作。 在看到您的更新之前,我最终选择了第二个。我创建了一个视图,然后使用 SQL 从我的 c# 程序调用该视图,其中包括 where 语句和公司 ID 的参数。它完全按照我的需要工作。我是一个自学 SQL 的人,所以一旦它起作用,我往往会停止寻找。但是,我将尝试更多地了解您的解决方案是如何工作的。非常感谢您的帮助。

以上是关于选择具有最长日期和其他条件的行的主要内容,如果未能解决你的问题,请参考以下文章

如何选择具有最大值的行的所有列

SQL选择具有最大和最小日期的行

Oracle SQL 选择具有开始和结束日期的行,如果某些重叠合并行

s-s-rS - 用于计算当前日期匹配或(参数选择日期)与其他一些等效列的行的表达式

选择具有最大 ID 和特定条件的行

选择最新的行并且恰好 2 行具有一个条件和 2 行具有不同的条件