在备用行上使用 LAG/LEAD 缺少 PK

Posted

技术标签:

【中文标题】在备用行上使用 LAG/LEAD 缺少 PK【英文标题】:Using LAG/LEAD with missing PK on alternate rows 【发布时间】:2020-12-18 15:52:58 【问题描述】:

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

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

该表源自我使用 OPENROWSET 导入的 excel 数据提取。

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

预期输出:

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

显然,有点挑战,因为下一行没有PK,如果我无法识别用于“分区”记录的值,我无法准确使用LEAD功能。有什么想法吗?

我已经包含了相同的值/代码:

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 

【问题讨论】:

您可以将其加载到带有IDENTITY() 的表格中吗(同时保留 Excel 中的顺序)? @HoneyBadger - 我能够成功实现这一点!感谢您的建议! 您可以回答自己的问题,如果您认为这对处于类似情况的其他人有帮助。 @HoneyBadger 完成! 【参考方案1】:

如果没有定义行顺序的列,则无法解决问题 - SQL 表的行在设计上是无序

如果您有一个排序列,您可以这样做:

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

【讨论】:

【参考方案2】:

根据@Honeybadger 的建议,我在创建临时登陆表时实现了IDENTITY(1,1) 属性。这在我加载数据时捕获了自然行序列。像魅力一样工作!

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

【讨论】:

以上是关于在备用行上使用 LAG/LEAD 缺少 PK的主要内容,如果未能解决你的问题,请参考以下文章

Windows Server 2016 安装 IIS 服务时提示指定备用源路径

pyspark 是不是支持窗口函数(例如 first、last、lag、lead)?

Nginx:备用域的不同 robots.txt

Hive函数:LAG,LEAD,FIRST_VALUE,LAST_VALUE

sql SQL Server 2012 TSQL新函数LAG,LEAD,FIRST_VALUE和LAST_VALUE

如何在 C# 中使用 Enumerable 获取备用元素