更改表中的“排名”并将连续行转换为单行

时间:2017-08-04 16:21:15

标签: sql sql-server

这是源表emp, 查看下表中的表格和所需输出:

EMP: 这里是来源表:

EMPID    ENAME    STANDING    DATE
101       ABC      ACTIVE      10-06-91
101       ABC      INACTIVE   01-07-2002
102       EFG      INACTIVE   02-09-2009
102       EFG      ACTIVE     01-10-2011
102       EFG      INACTIVE   07-10-2017
103       XYZ      ACTIVE     08-07-2010
103       XYZ      ACTIVE     08-07-2010
103       XYZ      INACTIVE   09-10-2011

输出:

EMPID     ENAME    BEFORESTANDING        CURRENTSTANDING    DATE
101       ABC       ACTVE                INACTIVE           01-07-2002
102       EFG       INACTIVE             ACTIVE             01-10-2011
102       EFG       ACTIVE               INACTIVE           07-10-2017
103       XYZ       ACTIVE               INACTIVE           09-10-2011

转换规则逻辑是指如果empid是相同的并且它已将STANDING从活动更改为非活动状态, 输出将在一行中,日期库存将来自最新记录。

如果表有三个非活动状态到活动状态并且活动状态为非活动状态,我们将在输出中保留2行[(n-1)用于输出] 随着积分的变化

如果表格在连续的行中有相同的排名,那么将跳过第一个,只考虑排名的变化。

3 个答案:

答案 0 :(得分:1)

如果您使用的是SQL Server 2012或更高版本,则可以使用LAG()函数

轻松完成此操作
WITH CTE_Source AS
(
    SELECT *
    , LAG(STANDING) OVER (PARTITION BY EmpID, Ename ORDER BY DATE) AS BEFORE_STANDING
    FROM Emp
)
SELECT * 
FROM CTE_Source
WHERE BEFORE_STANDING <> STANDING

SQLFiddle DEMO

答案 1 :(得分:0)

假设您使用的是SQL Server 2012或更高版本,以下应该可以解决问题...

IF OBJECT_ID('tempdb..#TestData', 'U') IS NOT NULL 
DROP TABLE #TestData;

CREATE TABLE #TestData (
    EMPID INT NOT NULL,
    ENAME CHAR(3) NOT NULL,
    STANDING VARCHAR(10) NOT NULL,
    [DATE] DATE NOT NULL 
    );
INSERT #TestData (EMPID, ENAME, STANDING, [DATE]) VALUES
    ('101', 'ABC', 'ACTIVE  ', '10-06-1991'),
    ('101', 'ABC', 'INACTIVE', '01-07-2002'),
    ('102', 'EFG', 'INACTIVE', '02-09-2009'),
    ('102', 'EFG', 'ACTIVE  ', '01-10-2011'),
    ('102', 'EFG', 'INACTIVE', '07-10-2017'),
    ('103', 'XYZ', 'ACTIVE  ', '08-07-2010'),
    ('103', 'XYZ', 'ACTIVE  ', '08-07-2010'),
    ('103', 'XYZ', 'INACTIVE', '09-10-2011');

--=============================================

WITH 
    cte_AddBeforeStanding AS (
        SELECT 
            td.EMPID,
            td.ENAME,
            BEFORESTANDING = LAG(td.STANDING, 1) OVER (PARTITION BY td.EMPID ORDER BY td.DATE),
            CURRENTSTANDING = td.STANDING,
            td.DATE
        FROM 
            #TestData td
        )
SELECT 
    bs.EMPID,
    bs.ENAME,
    bs.BEFORESTANDING,
    bs.CURRENTSTANDING,
    bs.DATE
FROM 
    cte_AddBeforeStanding bs
WHERE 
    bs.BEFORESTANDING <> bs.CURRENTSTANDING;
HTH,Jason

答案 2 :(得分:0)

如果您使用LAG

SQL SERVER 2012+是最好的方法,如果您使用的是旧版本,那么有一些方法可以做到这一点

Cross Apply

SELECT a.EMPID,
       a.ENAME,
       BEFORESTANDING= cs.STANDING,
       CURRENTSTANDING= a.STANDING,
       a.date
FROM   Yourtable a
       CROSS apply (SELECT TOP 1 *
                    FROM   Yourtable b
                    WHERE  a.EMPID = b.EMPID
                           AND a.DATE > b.DATE
                    ORDER  BY b.Date DESC) AS cs 

SELF JOIN

WITH CTE
     AS (SELECT *,
                Rn = Row_number()OVER(partition BY EMPID ORDER BY DATE)
         FROM   Yourtable)
SELECT a.EMPID,
       a.ENAME,
       BEFORESTANDING = b.STANDING,
       CURRENTSTANDING= a.STANDING,
       a.DATE
FROM   CTE a
       JOIN CTE b
         ON a.EMPID = b.EMPID
            AND a.Rn = b.Rn + 1
WHERE  a.STANDING <> b.STANDING
ORDER  BY a.EMPID,
          a.DATE