Sql server 2012 比较SQL中以前的数据行

Sql server 2012 比较SQL中以前的数据行,sql-server-2012,Sql Server 2012,这是一个相当新的概念,我正在使用SQL Server 2012 我在不同的论坛上对此进行了研究,但似乎我找不到问题的答案。这似乎是一个简单的查询(我尝试过使用temp变量来更新、延迟、CTE…等等),但我就是无法让它工作。谢谢你的帮助,因为我已经被困了好几天了 已经有一个源数据表(emp、hourly、date和seq),其中包含所有基本数据。我只需要创建3个新列,“last change date”、“last change seq”和“previous hourly”,并将这些数据值插入除最

这是一个相当新的概念,我正在使用SQL Server 2012

我在不同的论坛上对此进行了研究,但似乎我找不到问题的答案。这似乎是一个简单的查询(我尝试过使用temp变量来更新、延迟、CTE…等等),但我就是无法让它工作。谢谢你的帮助,因为我已经被困了好几天了

已经有一个源数据表(emp、hourly、date和seq),其中包含所有基本数据。我只需要创建3个新列,“last change date”、“last change seq”和“previous hourly”,并将这些数据值插入除最早的行之外的每个现有行中的3个新列中。因此,对于2017年3月5日的行,我希望看到“最后更改日期”为2016年6月5日,“最后更改顺序”为1,“上一小时”为45.55,对于2016年6月6日的行,“最后更改日期”为2016年1月10日,“最后更改顺序”为0,“上一小时”为42.37…等等

DECLARE @hrly_chg TABLE([emp] char(1),[hourly] numeric (15, 6), [date] DATETIME, [seq] INT);    
INSERT INTO @hrly_chg VALUES ('A', 46.23,'03/05/2017',0);    
INSERT INTO @hrly_chg VALUES ('A',45.55,'6/6/2016',0);    
INSERT INTO @hrly_chg VALUES ('A',45.55,'6/5/2016',1);    
INSERT INTO @hrly_chg VALUES ('A',42.37,'6/5/2016',0);    
INSERT INTO @hrly_chg VALUES ('A',42.37,'1/10/2016',0);    
INSERT INTO @hrly_chg VALUES ('A',41.54,'8/16/2015',1);    
INSERT INTO @hrly_chg VALUES ('A',38.33,'8/16/2015',0);    
INSERT INTO @hrly_chg VALUES ('A',38.33,'2/8/2015',0);    
INSERT INTO @hrly_chg VALUES ('A',38.33,'1/20/2015',0);    
INSERT INTO @hrly_chg VALUES ('A',31.20,'1/10/2015',0);    
INSERT INTO @hrly_chg VALUES ('A',31.20,'1/9/2015',0);    
INSERT INTO @hrly_chg VALUES ('A',31.20,'1/8/2015',0);    
INSERT INTO @hrly_chg VALUES ('A',31.20,'12/14/2014',0);    
INSERT INTO @hrly_chg VALUES ('A',31.20,'8/19/2014',0);    
INSERT INTO @hrly_chg VALUES ('A',31.20,'8/19/2014',1);    
INSERT INTO @hrly_chg VALUES ('A',26.73,'1/1/2014',0);    
INSERT INTO @hrly_chg VALUES ('A',25.22,'8/19/2013',0);    
提前谢谢

编辑1:订单将按日期和顺序排序

编辑2(jpeg格式的理想输出): 看看这个

因为您提到了滞后函数,所以这是实现这一点最简单的方法

select @@version as 'sql server version'


DECLARE @hrly_chg TABLE([emp] char(1),[hourly] numeric (15, 6), [date] DATETIME, [seq] INT);

INSERT INTO @hrly_chg VALUES ('A', 46.23,'03/05/2017',0);
INSERT INTO @hrly_chg VALUES ('A',45.55,'6/6/2016',0);
INSERT INTO @hrly_chg VALUES ('A',45.55,'6/5/2016',1);
INSERT INTO @hrly_chg VALUES ('A',42.37,'6/5/2016',0);
INSERT INTO @hrly_chg VALUES ('A',42.37,'1/10/2016',0);
INSERT INTO @hrly_chg VALUES ('A',41.54,'8/16/2015',1);
INSERT INTO @hrly_chg VALUES ('A',38.33,'8/16/2015',0);
INSERT INTO @hrly_chg VALUES ('A',38.33,'2/8/2015',0);
INSERT INTO @hrly_chg VALUES ('A',38.33,'1/20/2015',0);
INSERT INTO @hrly_chg VALUES ('A',31.20,'1/10/2015',0);
INSERT INTO @hrly_chg VALUES ('A',31.20,'1/9/2015',0);
INSERT INTO @hrly_chg VALUES ('A',31.20,'1/8/2015',0);
INSERT INTO @hrly_chg VALUES ('A',31.20,'12/14/2014',0);
INSERT INTO @hrly_chg VALUES ('A',31.20,'8/19/2014',0);
INSERT INTO @hrly_chg VALUES ('A',31.20,'8/19/2014',1);
INSERT INTO @hrly_chg VALUES ('A',26.73,'1/1/2014',0);
INSERT INTO @hrly_chg VALUES ('A',25.22,'8/19/2013',0);

declare @HourlyNew table ([emp] char(1),[hourly] numeric (15, 6), [date] DATETIME, [seq] INT,[LastChangeDate] datetime, LastChangeSEQ INT,[PreviousHourly] numeric(15,6))

insert into @HourlyNew (Emp,Hourly,Date,Seq)
select * from @Hrly_Chg

select h.emp,h.hourly,h.date,h.seq
,LAG(Date, 1,1) OVER (partition by emp ORDER BY date ,seq desc) AS PreviousDate 
,LAG(Seq, 1,1) OVER (partition by emp ORDER BY date ,seq desc) AS PreviousSeq 
,LAG(hourly, 1,1) OVER (partition by emp ORDER BY date ,seq desc) AS PreviousHourly  

from @HourlyNew h
产生


这将使用示例数据设置返回所需的结果集。这不需要使用任何CTE,我只是发现它更容易遵循

我不理解您是否需要根据问题更新表中的现有值,或者是否只需要返回与附件匹配的输出

如果您需要在现有表中插入或更新记录,这几乎可以让您一直做到这一点。尝试将此处的最终查询放入另一个CTE或temp表中,然后将
合并到现有表中以执行upsert

第一个CTE获取
每小时更改的记录。在第二个CTE中,我们添加上一个和下一个更改的值

或者最后一个查询将所有信息汇集在一起,生成我们的输出

查询

-- get hourly change dates
;with setup as (
select  hr.emp,
        hr.seq,
        hr.hourly,          
        case when hr.hourly != lag(hr.hourly,1,1) over (partition by hr.emp order by date asc, hr.seq asc) 
            or row_number() over (partition by hr.emp order by hr.date asc, hr.seq asc) = 1 -- first row can't lag
                then hr.[date]
                else null
        end ChangedDate
from @hrly_chg hr
)
-- add previous and next change date & hourly
, setup2 as
(
    select  s1.emp,
            s1.ChangedDate,
            s1.seq,
            s1.hourly as NewHourly,
            lag(s1.Hourly, 1, null) over (partition by s1.emp order by s1.ChangedDate asc, s1.seq asc) as PreviousHourly,
            lag(s1.ChangedDate, 1, null) over (partition by s1.emp order by s1.ChangedDate asc, s1.seq asc) as LastChangedDate,
            lead(s1.ChangedDate, 1, null) over (partition by s1.emp order by s1.ChangedDate asc, s1.seq asc) as NextChangedDate
    from setup s1
    where s1.ChangedDate is not null
)

select  hr.emp,
        cast(hr.[date] as date) as effdt,
        hr.seq,
        cast (hr.hourly as money) as hourly, 
        cast(s.LastChangedDate as date) as LastChangeDate,
        cast(s.PreviousHourly as money) as PreviousHourly
from @hrly_chg hr
left join setup2 s 
on hr.emp = s.emp
and ( 
    -- assign values to same record
    (hr.[date] = s.ChangedDate and s.seq = hr.seq)
    -- assign values to inbetween records
    or  (hr.[date] > s.ChangedDate and hr.[date] < s.NextChangedDate)
    -- assign values where hourly changes in next sequence on same day
    or  (hr.[date] = s.NextChangedDate and hr.hourly = s.NewHourly)
    -- assign values where hourly changes in previous sequence on same day
    or  (hr.[date] = s.ChangedDate and hr.hourly = s.NewHourly)
    )
order by hr.[date], hr.seq

你能不能把你的样本输出做成一个很好的表格格式,这样我们就可以讨论它了?还有一个问题:你定义前一行的输入记录的顺序是什么?我添加了两个编辑。数据应该按日期排序,然后按顺序排序,这就是“上一行”的定义方式。我还附上了一个jpeg的理想输出应该是什么。谢谢。我看到您选择了按日期排序的
,seq**desc**
条款。这不是有点违反直觉吗?这是真的。其思想是获取最高的序号,因此如果有多条记录的日期相同,则LAG函数应获取最高(最近插入的)记录。OP可能需要调整代码以适应其特定的应用,但这是一般的想法。我可能遗漏了一些东西。。。按顺序排序是否意味着滞后函数将获取最低值,而不是最高值?Aron,谢谢。我做过类似的运行,但它没有给我理想的结果,因为在同一个日期中可能有多行(通过不同的seq#进行区分,因此emp+date+seq是唯一的标识符),而LAG不会查找“真正的”前一行。我已经添加了一个jpeg来显示所需的输出。在这种情况下,将这些列添加到您的滞后分区
,滞后(日期,1,1)超过(按emp分区,日期,按日期顺序,seq desc)作为前一个日期
,我不经常使用滞后,所以您可能需要使用它,但它肯定可以做到。另一个选项很混乱——您必须使用子查询,而且要复杂得多。让我知道,如果你不能得到滞后工作,虽然Hi-Rex,服务器已关闭,但你发布的输出和查询看起来很有希望。我将在服务器启动时尝试它的速度。谢谢你的建议。
+-----+------------+-----+--------+----------------+----------------+
| emp |   effdt    | seq | hourly | LastChangeDate | PreviousHourly |
+-----+------------+-----+--------+----------------+----------------+
| A   | 2013-08-19 |   0 | 25.22  | NULL           | NULL           |
| A   | 2014-01-01 |   0 | 26.73  | 2013-08-19     | 25.22          |
| A   | 2014-08-19 |   0 | 31.20  | 2014-01-01     | 26.73          |
| A   | 2014-08-19 |   1 | 31.20  | 2014-01-01     | 26.73          |
| A   | 2014-12-14 |   0 | 31.20  | 2014-01-01     | 26.73          |
| A   | 2015-01-08 |   0 | 31.20  | 2014-01-01     | 26.73          |
| A   | 2015-01-09 |   0 | 31.20  | 2014-01-01     | 26.73          |
| A   | 2015-01-10 |   0 | 31.20  | 2014-01-01     | 26.73          |
| A   | 2015-01-20 |   0 | 38.33  | 2014-08-19     | 31.20          |
| A   | 2015-02-08 |   0 | 38.33  | 2014-08-19     | 31.20          |
| A   | 2015-08-16 |   0 | 38.33  | 2014-08-19     | 31.20          |
| A   | 2015-08-16 |   1 | 41.54  | 2015-01-20     | 38.33          |
| A   | 2016-01-10 |   0 | 42.37  | 2015-08-16     | 41.54          |
| A   | 2016-06-05 |   0 | 42.37  | 2015-08-16     | 41.54          |
| A   | 2016-06-05 |   1 | 45.55  | 2016-01-10     | 42.37          |
| A   | 2016-06-06 |   0 | 45.55  | 2016-01-10     | 42.37          |
| A   | 2017-03-05 |   0 | 46.23  | 2016-06-05     | 45.55          |
+-----+------------+-----+--------+----------------+----------------+