比较SQL

时间:2017-04-19 19:35:18

标签: sql-server-2012

相当新,我正在使用SQL Server 2012。

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

已有一个源数据表(emp,hourly,date和seq),其中包含所有基本数据。我只需要创建3个新列,"最后更改日期","最后更改seq"和"之前的每小时",并将这些数据值插入到除最早行之外的每个现有行中的3个新列中。因此,对于3/5/2017行,我希望看到"最后更改日期" 2016年6月5日,"最后一次更改seq"是1,"前一小时" 45.55,2016年6月6日行,"最后更改日期"将是2016年1月10日,"最后一次改变seq"是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中的理想输出): Hourly rate change output

2 个答案:

答案 0 :(得分:0)

看看这个

http://rextester.com/UILB97912

由于您提到了LAG功能,这是实现此目的的最简单方法。

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

产生

enter image description here

答案 1 :(得分:0)

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

如果您需要更新问题中表格中的现有值,或者您只需要返回与附件匹配的输出,我就没有表态。

如果您需要在现有表格中插入或更新记录,这将使您几乎一路走来。尝试将最终查询放入另一个CTE或临时表,并merge放入现有表中以执行upsert。

第一个CTE获取hourly更改的记录。在第二个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

<强>输出

+-----+------------+-----+--------+----------------+----------------+
| 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          |
+-----+------------+-----+--------+----------------+----------------+