如何根据创建标识符和最大日期的两列选择行
Posted
技术标签:
【中文标题】如何根据创建标识符和最大日期的两列选择行【英文标题】: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, ...
以减少代码混乱。
【参考方案1】:
GROUP BY 子句将所有包含指定列中数据的行聚集在一起(这里 GroupBy 操作对列 L.ItemNo
、L.Lot
、L.Description
和 L.Quantity
执行)并允许聚合在一列或多列上执行的函数(这里聚合在L.PostingDate
上完成)。
因此,每条具有不同列组合的记录,即L.ItemNo
、L.Lot
、L.Description
和L.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
因此,当您对Identifier
、ItemNo
、Description
、Quantity
和 Lot
进行分组时,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
所在行的PostingDate
和Quantity
的值:
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
【讨论】:
这行得通。非常感谢您的帮助!以上是关于如何根据创建标识符和最大日期的两列选择行的主要内容,如果未能解决你的问题,请参考以下文章