在交替行上使用缺少 PK 的 LAG/LEAD

Using LAG/LEAD with missing PK on alternate rows

我正在尝试在 SQL Server 2012 中使用以下 table:

EMPID    JOB_TITLE            SALARY
------------------------------------
1234     SALES                56000
NULL     NULL                 54000
1235     MARKETING            72000
NULL     NULL                 71000

table 源自 excel 提取,为此我使用 OPENROWSET 导入。

我需要导出“先前的”薪水值,您可以假设它始终以 table 中的自然顺序存在于以下记录中,并将其显示为新列。

预期输出:

EMPID    JOBTITLE            SALARY    PREV_SALARY
--------------------------------------------------
1234     BUSINESS ANALYST     56000     54000
1235     SALES MANAGER        72000     71000
                              

显然,有点挑战,因为下一行没有主键,如果我不能识别用来“分区”记录的值,我就不能准确地使用 LEAD 函数。有什么想法吗?

我添加了相同的内容 values/code:

INSERT INTO #EMP 
VALUES (1234, 'Sales', 56000), 
       (NULL, NULL, 54000),
       (1235, 'Marketing', 72000),
       (NULL, NULL, 70500) 
                                
SELECT 
    EMPID, 
    JOBTITLE,
    SAL,
    LEAD(SAL,1,0) OVER (ORDER BY NEWID()) AS PREV_SAL
FROM 
    #EMP       
WHERE 
    EMPID IS NOT NULL 

如果没有定义行排序的列,则问题无法解决 - SQL table 的行 未排序 设计.

如果你有一个排序栏,你可以这样做:

select *
from (
    select e.*, lead(salary) over(order by id) as prev_salary
    from employee e
) t
where empid is not null

这假定非空行和空行始终正确交错。如果不是这种情况,那么我会推荐一些间隙和岛屿技术,如:

select max(empid) as empid, 
    max(case when rn = 1 then job_title end) as job_title, 
    max(case when rn = 1 then salary    end) as salary,
    max(case when rn = 2 then salary    end) as prev_salary
from (
    select e.*, row_number() over(partition by grp order by empid) rn
    from (
        select e.*, count(empid) over(order by id) as grp
        from employee e
    ) t
) t
group by grp

根据@Honeybadger的建议,我在创建临时登陆的时候实现了IDENTITY(1,1)属性table。这在我加载数据时捕获了自然行序列。很有魅力!

CREATE TABLE #EMP 
(
 EMPID INT
, JOBTITLE NVARCHAR(19)
, SAL INT
, ROW_SEQ INT IDENTITY(1,1) 
) 



INSERT INTO #EMP 
VALUES (1234, 'Sales', 56000), 
       (NULL, NULL, 54000),
       (1235, 'Marketing', 72000),
       (NULL, NULL, 70500) 
 
SELECT * FROM (
SELECT 
    EMPID, 
    JOBTITLE,
    SAL,
    LEAD(SAL,1,0) OVER (ORDER BY ROW_SEQ ) AS PREV_SAL
FROM  #EMP )  T WHERE EMPID IS NOT NULL 

输出:

EMPID   JOBTITLE    SAL     PREV_SAL
1234    Sales       56000   54000
1235    Marketing   72000   70500