SQL Server 2008 R2:将列拆分为两部分

问题描述:

我有下列表,称为tbl_Rightstbl_Rights_history,其中包含有关雇员权利和修改历史记录的 信息。SQL Server 2008 R2:将列拆分为两部分

表结构:

CREATE TABLE Tbl_Rights 
(
    Rights_ID int, 
    Rights_name varchar(10) 
); 

CREATE TABLE Tbl_Rights_history 
(
    EMPID int, 
    EMPName varchar(50), 
    Rights_ID int, 
    ModifiedDate datetime 
); 

插入数据:

INSERT INTO Tbl_Rights VALUES(1,'Guest') 
INSERT INTO Tbl_Rights VALUES(2,'Admin') 

INSERT INTO Tbl_Rights_history VALUES(1,'Sam',1,'2010-01-01 10:12:02.563') 
INSERT INTO Tbl_Rights_history VALUES(1,'Sam',2,'2010-01-02 11:32:10.125') 
INSERT INTO Tbl_Rights_history VALUES(1,'Sam',1,'2010-01-03 12:22:11.478') 
INSERT INTO Tbl_Rights_history VALUES(2,'Mak',1,'2010-02-01 11:44:16.196') 
INSERT INTO Tbl_Rights_history VALUES(2,'Mak',2,'2010-03-02 12:37:26.568') 

预期输出:

EMPName Old_Rights New_Rights ModifiedDate_1    ModifiedDate_2 
---------------------------------------------------------------------------------- 
Sam  Guest  Admin  2010-01-01 10:12:02.563  2010-01-02 11:32:10.127 
Sam  Admin  Guest  2010-01-02 11:32:10.127  2010-01-03 12:22:11.477 
Mak  Guest  Admin  2010-02-01 11:44:16.197  2010-03-02 12:37:26.567 

我尝试:

;WITH CTE1 AS 
(
    SELECT t1.EMPID, 
      t1.EMPName, 
      t2.Rights_name, 
      t1.ModifiedDate, 
      DENSE_RANK() OVER(PARTITION BY t1.EMPID ORDER BY t1.ModifiedDate ASC) rn 
    FROM Tbl_Rights_history t1 
    LEFT JOIN Tbl_Rights t2 
     ON t1.Rights_ID = t2.Rights_ID 
) 
SELECT c.EMPName, 
     CASE WHEN rn = 1 THEN c.Rights_Name END Old_Rights, 
     CASE WHEN rn > 1 THEN c.Rights_Name END New_Rigths, 
     CASE WHEN rn = 1 THEN c.ModifiedDate END ModifiedDate_1, 
     CASE WHEN rn > 1 THEN c.ModifiedDate END ModifiedDate_2 
FROM CTE1 c; 

但是,得到意想不到的输出:

EMPName Old_Rights New_Rigths ModifiedDate_1   ModifiedDate_2 
------------------------------------------------------------------------------- 
Sam  Guest  NULL  2010-01-01 10:12:02.563 NULL 
Sam  NULL  Admin  NULL     2010-01-02 11:32:10.127 
Sam  NULL  Guest  NULL     2010-01-03 12:22:11.477 
Mak  Guest  NULL  2010-02-01 11:44:16.197 NULL 
Mak  NULL  Admin  NULL     2010-03-02 12:37:26.567  

你可以试试这个

;WITH T AS (
    SELECT t1.*, 
     t2.Rights_name, 
     RN=ROW_NUMBER() OVER(PARTITION BY EMPID ORDER BY ModifiedDate ASC) 
    FROM Tbl_Rights_history t1 
     LEFT JOIN Tbl_Rights t2 ON t1.Rights_ID = t2.Rights_ID 
) 
SELECT 
    T1.EMPName, 
    T2.Rights_name Old_Rights, 
    T1.Rights_name New_Rights, 
    T2.ModifiedDate ModifiedDate_1, 
    T1.ModifiedDate ModifiedDate_2 
FROM T T1 
    INNER JOIN T T2 ON T1.RN = T2.RN +1 AND T1.EMPID = T2.EMPID 

结果:

EMPName  Old_Rights New_Rights ModifiedDate_1   ModifiedDate_2 
----------- ---------- ---------- ----------------------- ----------------------- 
Sam   Guest  Admin  2010-01-01 10:12:02.563 2010-01-02 11:32:10.127 
Sam   Admin  Guest  2010-01-02 11:32:10.127 2010-01-03 12:22:11.477 
Mak   Guest  Admin  2010-02-01 11:44:16.197 2010-03-02 12:37:26.567 
+0

什么是优雅的解决方案 –

declare @Tbl_Rights table(
Rights_ID int 
, Rights_Name nvarchar(10) 
); 
declare @Tbl_Rights table(
    Rights_ID int 
, Rights_Name nvarchar(10) 
); 

declare @Tbl_Rights_history table(
    EMPID  int 
, EMPName  nvarchar(50) 
, Rights_ID int 
, ModifiedDate datetime 
); 

insert @Tbl_Rights 
values (1, N'Guest') 
    , (2, N'Admin') 
    , (3, N'User') 

insert @Tbl_Rights_history 
values (1, N'Sam', 1, '2010-01-01T10:12:02.563') 
    , (1, N'Sam', 2, '2010-01-02T11:32:10.125') 
    , (1, N'Sam', 1, '2010-01-03T12:22:11.478') 
    , (2, N'Mak', 1, '2010-02-01T11:44:16.196') 
    , (2, N'Mak', 2, '2010-03-02T12:37:26.568') 
    , (3, N'Nik', 3, '2010-03-02T12:37:26.568') 

;with cte as(
select 
    trh.* 
, row_Number() over (partition by trh.EMPID order by trh.ModifiedDate desc) as RN 
, tr.Rights_Name 
from @Tbl_Rights_history trh 
    join @Tbl_Rights tr on tr.Rights_ID = trh.Rights_ID 
) 
select 
    new.EMPName 
, old.Rights_Name as RightsOld 
, new.Rights_Name as RightsNew 
, old.ModifiedDate as ModifiedDateOld 
, new.ModifiedDate as ModifiedDateNew 
from cte new 
    left join cte old on old.EMPID = new.EMPID and old.RN = 2 
where new.RN = 1 

结果:

EMPName RightsOld RightsNew ModifiedDateOld ModifiedDateNew 
------- ---------- ---------- ----------------- ------------------- 
Sam  Admin  Guest  2010-01-02 11:32 2010-01-03 12:22:11 
Mak  Guest  Admin  2010-02-01 11:44 2010-03-02 12:37:26 
Nik  NULL  User  NULL    2010-03-02 12:37:26 
(3 row(s) affected)