在SQL中部分UNPIVOT成对的更好方法

时间:2011-06-14 18:43:02

标签: sql sql-server-2008

我有下表

VendorID    EMP1A       EMP2A       EMP1B       EMP2B
----------- ----------- ----------- ----------- -----------
1           4           3           5           4
2           4           1           5           5
3           4           3           5           4
4           4           2           5           5
5           5           1           5           5

我想成对UNPIVOT,所以我在一行上获得“A”列,在另一行上获得“B”列

vendorid    employee  orders      employee  orders
----------- --------- ----------- --------- -----------
1           EMP1A     4           EMP2A     3
1           EMP1B     5           EMP2B     4
2           EMP1A     4           EMP2A     1
2           EMP1B     5           EMP2B     5
3           EMP1A     4           EMP2A     3
3           EMP1B     5           EMP2B     4
4           EMP1A     4           EMP2A     2
4           EMP1B     5           EMP2B     5
5           EMP1A     5           EMP2A     1
5           EMP1B     5           EMP2B     5

这样可行,但似乎我工作太辛苦了

DECLARE @pvt AS TABLE( 
  VendorID INT, 
  EMP1A    INT, 
  EMP2A    INT, 
  EMP1B    INT, 
  EMP2B    INT); 

INSERT INTO @pvt VALUES (1,4,3,5,4),
(2,4,1,5,5),
(3,4,3,5,4),
(4,4,2,5,5),
(5,5,1,5,5)

;WITH piv1 
     AS (SELECT vendorid, 
                employee, 
                orders 
         FROM   (SELECT vendorid, 
                        EMP1A, 
                        EMP1B 
                 FROM   @pvt) p 
                 UNPIVOT (orders FOR employee IN (EMP1A, EMP1B) ) 
                AS 
                unpvt), 
     piv2 
     AS (SELECT vendorid, 
                employee, 
                orders 
         FROM   (SELECT vendorid, 
                        EMP2A, 
                        EMP2B 
                 FROM   @pvt) p UNPIVOT (orders FOR employee IN (EMP2A, EMP2B) ) 
                AS 
                unpvt) 
SELECT piv1.vendorid, 
       piv1.employee, 
       piv1.orders, 
       piv2.employee, 
       piv2.orders 
FROM   piv1 
       INNER JOIN piv2 
         ON piv1.vendorid = piv2.vendorid 
            AND RIGHT(piv1.employee, 1) = RIGHT(piv2.employee, 1) 
WHERE
    piv1.orders > piv2.orders

注意:这是一个简化的示例,实际上有25对需要转换为行,我也希望能够轻松过滤

e.g。添加WHERE piv1.orders = piv2.orders生成

vendorid    employee  orders      employee  orders
----------- --------- ----------- --------- -----------
2           EMP1B     5           EMP2B     5
4           EMP1B     5           EMP2B     5
5           EMP1B     5           EMP2B     5

2 个答案:

答案 0 :(得分:1)

这很简单吗?

SELECT
   vendorid,
   'EMP1A' AS employee, EMP1A AS [order1],
   'EMP2A' AS employee, EMP2A AS [order2]
FROM Mytable
UNION ALL
SELECT
   vendorid,
   'EMP1B', EMP1B,
   'EMP2B', EMP2B
FROM Mytable

注意:您的列名称不明确会破坏使用此数据的其他内容

要获取更多行,请添加UNION子句

...
UNION ALL
SELECT
   vendorid,
   'EMP1C', EMP1C,
   'EMP2C', EMP2C
FROM Mytable
UNION ALL
SELECT
   vendorid,
   'EMP1D', EMP1D,
   'EMP2D', EMP2D
FROM Mytable
...

进一步过滤(需要不同的列名)

SELECT ...
FROM
    (
    SELECT
       vendorid,
       'EMP1A' AS employee1, EMP1A AS [order1],
       'EMP2A' AS employee2, EMP2A AS [order2]
    FROM Mytable
    UNION ALL
    SELECT
       vendorid,
       'EMP1B', EMP1B,
       'EMP2B', EMP2B
    FROM Mytable
    UNION ALL
    SELECT
       vendorid,
       'EMP1C', EMP1C,
       'EMP2C', EMP2C
    FROM Mytable
    UNION ALL
    SELECT
       vendorid,
       'EMP1D', EMP1D,
       'EMP2D', EMP2D
    FROM Mytable
    ...
   ) foo
WHERE
   order1 = order2

答案 1 :(得分:1)

事实证明我工作太辛苦了

WITH piv1 
     AS (SELECT vendorid, 
                employee, 
                orders 
         FROM   @pvt p UNPIVOT (orders FOR employee IN (emp1a, emp1b, 
                                                        emp2a, emp2b) ) 
                AS unpvt) 
SELECT piv1.vendorid, 
       piv1.employee, 
       piv1.orders, 
       piv2.employee, 
       piv2.orders 
FROM   piv1 
       INNER JOIN piv1 piv2 
         ON piv1.vendorid = piv2.vendorid 
            AND piv1.employee <> piv2.employee 
            AND RIGHT(piv1.employee, 1) = RIGHT(piv2.employee, 1) 
WHERE  Substring(piv1.employee, 4, 1) <> '2' 
ORDER  BY piv1.vendorid, 
          piv1.employee 

现在添加对只需要更新UNPIVOT e.g。

@pvt p UNPIVOT (orders FOR employee IN (emp1a, emp1b,
                                        emp2a, emp2b,
                                        emp1c, emp2c,
                                        emp1d, emp2d) )