【问题标题】:How to select rows based on two columns creating an identifier and the max date如何根据创建标识符和最大日期的两列选择行
【发布时间】:2021-08-19 21:01:48
【问题描述】:

我有六列。我自己创建的六列之一。将其中的两个列放在一起创建一个标识符列。我只想为标识符列的每个不同组合选择最大日期行。当我省略数量列时,我得到了预期的行数。但是,一旦我添加数量,它就会给我我不期望的行。如何只为 Identifier 列的每个不同出现选择最大日期行?

例如,当我运行此查询时...

Select 
 Distinct(L.ItemNo+' 'L.Lot) as Identifier
 ,Max(L.PostingDate)
 ,L.ItemNo
 ,L.Description
 ,L.Quantity
 ,L.Lot
From dbo.JournalLine L
Groupy by
 L.ItemNo
 ,L.Lot
 ,L.Description
 ,L.Quantity

我得到以下结果。我没想到的这一行是有 45 个苹果的那一行。

Identifier PostingDate ItemNo Description Quantity Lot
I123 LOT123 2021-06-01 I123 Celery 79 L123
I456 LOT456 2021-06-01 I456 Carrot 25 L456
I456 LOT654 2021-06-01 I654 Carrot 21 L654
I789 LOT789 2021-05-28 I789 Apple 45 L789
I789 LOT789 2021-06-01 I789 Apple 38 L789
I789 LOT555 2021-06-01 I789 Apple 11 L555

【问题讨论】:

  • DISTINCT 不是一个函数,它是一个设置量词,属于SELECT DISTINCT - 适用于整个选定的行。跳过那些额外的括号,直接写Select Distinct L.ItemNo+' 'L.Lot as Identifier, ... 以减少代码混乱。

标签: sql sql-server max distinct inventory


【解决方案1】:

GROUP BY 子句将所有包含指定列中数据的行聚集在一起(这里 GroupBy 操作对列 L.ItemNoL.LotL.DescriptionL.Quantity 执行)并允许聚合在一列或多列上执行的函数(这里聚合在L.PostingDate上完成)。

因此,每条具有不同列组合的记录,即L.ItemNoL.LotL.DescriptionL.Quantity,将与它的重复组合的聚合一起出现。例如,考虑您的示例:-

让我们假设您的表中有以下记录:-

Identifier  PostingDate ItemNo  Description Quantity    Lot
I789 LOT789 2021-05-27  I789    Apple       45          L789
I789 LOT789 2021-05-29  I789    Apple       38          L789
I789 LOT789 2021-05-25  I789    Apple       45          L789
I789 LOT789 2021-05-28  I789    Apple       45          L789
I789 LOT789 2021-06-01  I789    Apple       38.         L789
I789 LOT555 2021-06-01  I789    Apple       11.         L555

因此,当您对IdentifierItemNoDescriptionQuantityLot 进行分组时,SQL 会理解您想要对这些列进行逻辑分组,并且它将划分数据并理解如下:-

-- Group 1
Identifier  PostingDate ItemNo  Description Quantity    Lot
I789 LOT789 2021-05-27  I789    Apple       45          L789
I789 LOT789 2021-05-25  I789    Apple       45          L789
I789 LOT789 2021-05-28  I789    Apple       45          L789

-- Group 2
Identifier  PostingDate ItemNo  Description Quantity    Lot
I789 LOT789 2021-05-29  I789    Apple       38          L789
I789 LOT789 2021-06-01  I789    Apple       38.         L789

-- Group 3
Identifier  PostingDate ItemNo  Description Quantity    Lot
I789 LOT555 2021-06-01  I789    Apple       11.         L555

现在,当您在某个特定列上的这些记录上运行任何聚合函数时,它将尝试为遇到的每个逻辑分组运行聚合函数(如上所示,在这种情况下有 3 个)

因此,在我们的例子中,聚合函数是 Max(L.PostingDate),它将选择迄今为止已识别的每个组的最大日期记录,如下所示:-

-- Group 1
Identifier  PostingDate ItemNo  Description Quantity    Lot
I789 LOT789 2021-05-28  I789    Apple       45          L789

-- Group 2
Identifier  PostingDate ItemNo  Description Quantity    Lot
I789 LOT789 2021-06-01  I789    Apple       38.         L789

-- Group 3
Identifier  PostingDate ItemNo  Description Quantity    Lot
I789 LOT555 2021-06-01  I789    Apple       11.         L555

现在最后它结合了所有记录并显示结果如下:-

-- Final Ouput
Identifier  PostingDate ItemNo  Description Quantity    Lot
I789 LOT789 2021-05-28  I789    Apple       45          L789
I789 LOT789 2021-06-01  I789    Apple       38.         L789
I789 LOT555 2021-06-01  I789    Apple       11.         L555

这就是group by 的作用方式,所以在您的情况下,如果您不希望 group by 在quantity 列上发生,您可以简单地将其从 select 查询以及 groupBy 中删除,或者如果您包括 quantity 列以分组,它将继续打印具有不同列组合的记录。

【讨论】:

    【解决方案2】:

    你可以使用窗口功能:

    select * from (
      select * , row_number() over (partition by ItemNo,Lot order by PostingDate desc) rn
      from dbo.JournalLine
    ) l
    where rn = 1
    

    【讨论】:

      【解决方案3】:

      使用窗口函数MAX()FIRST_VALUE()分别获取最新PostingDate所在行的PostingDateQuantity的值:

      SELECT DISTINCT
             ItemNo + ' ' + Lot AS Identifier,
             MAX(PostingDate) OVER (PARTITION BY ItemNo, Lot, Description) AS PostingDate,
             ItemNo,
             Description,
             FIRST_VALUE(Quantity) OVER (PARTITION BY ItemNo, Lot, Description ORDER BY PostingDate DESC) AS Quantity,
             Lot
      FROM dbo.JournalLine
      

      【讨论】:

      • 这行得通。非常感谢您的帮助!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-01-31
      • 1970-01-01
      • 2016-06-10
      • 1970-01-01
      • 1970-01-01
      • 2021-02-02
      • 2023-03-07
      相关资源
      最近更新 更多