根据给定日期的条件及其先前行操作列检索最新行

Posted

技术标签:

【中文标题】根据给定日期的条件及其先前行操作列检索最新行【英文标题】:Retrieve latest rows based on the condition and its previous rows action column on a given date 【发布时间】:2020-09-11 09:16:35 【问题描述】:

数据集:

IF OBJECT_ID('tempdb..#temp') IS NOT NULL
    DROP TABLE #temp

CREATE TABLE #temp(
user_id [int]  NOT NULL,
date [datetime] NOT NULL,
fieldid [int] NOT NULL,
fieldvalue NVARCHAR(100) NOT NULL,
fromvalue [int] NULL,
tovalue [int]  NULL,
action char(1) NOT NULL,
audit_date [datetime] NOT  NULL
)

Insert into #temp values ( 1,'2020-01-01',1,'a',NULL,0,'C','2020-01-01 21:00:39.000 ');

Insert into #temp values ( 2,'2020-01-01',1,'a',NULL,0,'C','2020-01-01 21:00:39.000 ');
Insert into #temp values ( 2,'2020-01-01',1,'a',NULL,0,'N','2020-01-01 22:00:39.000 ');

Insert into #temp values ( 2,'2020-01-01',1,'b',NULL,0,'C','2020-01-01 21:00:39.000 ');
Insert into #temp values ( 2,'2020-05-05',1,'a',NULL,0,'C','2020-05-05 21:00:39.000 ');
Insert into #temp values ( 2,'2020-05-05',2,'a',NULL,0,'C','2020-05-05 21:00:39.000 ');
Insert into #temp values ( 2,'2020-05-05',1,'b',NULL,0,'C','2020-05-05 21:00:39.000 ');
Insert into #temp values ( 2,'2020-05-05',3,'c',NULL,0,'C','2020-05-05 21:00:39.000 ');

Insert into #temp values ( 3,'2020-01-02',1,'a',NULL,0,'C','2020-01-01 10:00:39.000 ');
Insert into #temp values ( 3,'2020-01-02',1,'a',NULL,0,'N','2020-01-01 11:00:39.000 ');
Insert into #temp values ( 3,'2020-01-02',1,'a',NULL,0,'C','2020-01-01 12:00:39.000 ');

Insert into #temp values ( 4,'2020-10-10',1,'a',NULL,0,'C','2020-01-01 22:00:39.000 ');
Insert into #temp values ( 4,'2020-10-10',1,'a',1   ,0,'U','2020-01-01 23:00:39.000 ');`

条件 当 fromvalue = 0 和 tovalue = 1 时仅包含最新行,对于给定的用户 ID、日期、字段 ID、字段值给定日期,操作 'N'

sql查询

with cte as
(
    select user_id, date, fieldid, fieldvalue, fromvalue, tovalue
        , action, audit_date
        ,  ROW_NUMBER() OVER(PARTITION BY user_id, date, fieldid, fieldvalue ORDER BY audit_date desc) AS 'rnk'
    from #temp (nolock)  
)
select * from cte where rnk = 1 and action <>'N'  and fromvalue IS NULL and  tovalue = 0 ;

我想现在得到了这个查询。到目前为止工作正常。请查看。

注意:根据有效评论编辑了原始帖子。我是新手,我将在以后发布 DTD。我道歉

【问题讨论】:

首先 - 停止喷溅nolock everywhere - 这不是最佳做法。接下来,通过发布包含 DDL 和示例数据的脚本来鼓励其他人帮助您。否则,你会把写这篇文章的工作推给你的读者。为什么这对你有帮助?一方面,您在 [table](顺便说一句,好名字)中没有名为 data_to_value 或 data_from_value 的列。编写脚本会发现那些错别字。还要注意你的名字中下划线的使用不一致。 不要在with前加上分号;,而是养成用分号结束所有语句的正确习惯。 根据评论编辑了原始问题。感谢@SMor 分享链接。我对此并不陌生,我很抱歉没有清楚地发布它。似乎查询正在运行 @SM我读了这篇文章,它建议使用 SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;你能分享一下你什么时候可以使用 nolock 什么时候不可以使用的想法吗?提前致谢 @Rocky3151 该链接的文章也有其他人的链接,您可以通过搜索互联网找到许多关于使用NOLOCK的文章。一般来说,您不会在不知道并接受后果的情况下使用该提示。不正确的数据和错误只是其中的一些问题。一般来说,很少有 IME 需要这种提示。我从来没有使用过这个提示 【参考方案1】:

您使用row_number() 的尝试非常有效,但是需要将整个过滤逻辑移动到计算窗口函数的子查询中。否则,不符合条件的行可能会排在第一位,然后在外部查询中排除。

这应该可以满足您的要求 - 请注意您对过滤规范的描述与查询不匹配(我使用了查询的谓词,它更好地匹配您的示例数据):

select *
from (
    select
        t.*,
        row_number() over(
            partition by user_id, date, fieldid, fieldvalue
            order by audit_date desc
        ) rn
    from #temp t
    where fromvalue is null and tovalue = 0 and action <> 'N'
) t
where rn = 1

对于您的示例数据,this produces

用户 ID |日期 |字段ID |字段值 |从值 |总价值 |行动 |审计日期 | rn ------: | :------------------------ | ------: | :--------- | --------: | ------: | :----- | :------------------------ | :- 1 | 2020-01-01 00:00:00.000 | 1 |一个 | | 0 | C | 2020-01-01 21:00:39.000 | 1 2 | 2020-01-01 00:00:00.000 | 1 |一个 | | 0 | C | 2020-01-01 21:00:39.000 | 1 2 | 2020-01-01 00:00:00.000 | 1 |乙 | | 0 | C | 2020-01-01 21:00:39.000 | 1 2 | 2020-05-05 00:00:00.000 | 1 |一个 | | 0 | C | 2020-05-05 21:00:39.000 | 1 2 | 2020-05-05 00:00:00.000 | 1 |乙 | | 0 | C | 2020-05-05 21:00:39.000 | 1 2 | 2020-05-05 00:00:00.000 | 2 |一个 | | 0 | C | 2020-05-05 21:00:39.000 | 1 2 | 2020-05-05 00:00:00.000 | 3 | c | | 0 | C | 2020-05-05 21:00:39.000 | 1 3 | 2020-01-02 00:00:00.000 | 1 |一个 | | 0 | C | 2020-01-01 12:00:39.000 | 1 4 | 2020-10-10 00:00:00.000 | 1 |一个 | | 0 | C | 2020-01-01 22:00:39.000 | 1

【讨论】:

谢谢@GMB。如果描述不准确,我深表歉意。与条件不匹配的行可能会排在第一位,然后在外部查询中被排除。你是对的,我只想包括条件的最新记录。考虑到这种情况,我共享的查询运行良好。感谢您的回复

以上是关于根据给定日期的条件及其先前行操作列检索最新行的主要内容,如果未能解决你的问题,请参考以下文章

MS Access Query 以检索订单日期列中最新日期的记录

根据行中的值检索(索引,列)对

20-7数据检索

使用 T-SQL 根据先前行的值逐行更新表

Pandas:如何从给定(行,列)对列表的 DataFrame 中检索值?

SqlServer--数据检索(查询)