2017-08-04 35 views
0

這是源表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 

OUTPUT:

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是相同的,它已經得到了積極的地位的變化,以inacti ve, 輸出將在單行和日期coulmn將從最新的記錄。

如果表已得到的非活動3個榜到活性和活動到非活動我們將保持在輸出[第(n-1),用於輸出] 2行與榜

如果表的變化在相繼的排中得到同樣的排名,然後跳過第一個,只考慮積分榜的變化。

+0

您使用的是哪個版本的SQL Server?在2012年(和更新版本)中,您可以使用[LAG()](https://docs.microsoft.com/zh-cn/sql/t-sql/functions/lag-transact-sql)函數很容易地執行此操作 –

回答

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 
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,傑森

+0

不會產生預期的結果 –

+0

更新了最終的WHERE子句。 –

+0

現在'bs.BEFORESTANDING不是NULL'條件是多餘的;)。如果你刪除它,那麼它是[Nenad Zivkovic](https://stackoverflow.com/a/45511869/3349551)answer;)的副本 –

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