不显示多列 - 使用CROSS APPLY将列名的子字符串作为新列

时间:2015-08-19 13:32:51

标签: sql-server unpivot cross-apply

我有一个格式如下的表格

YEAR, MONTH, ITEM,  REQ_QTY1, REQ_QTY2 , ....REQ_QTY31 ,CONVERTED1, CONVERTED2 ....CONVERTED31

每列的后缀是月份的日期。

我需要将其转换为以下格式,其中Day_of_month是每列的数字后缀

YEAR, MONTH, DAY_OF_MONTH, ITEM, REQ_QTY, CONVERTED

我想过使用CROSS APPLY来检索数据,但是我不能使用CROSS APPLY来获取“Day of Day”

SELECT A.YEAR, A.MONTH, A.ITEM, B.REQ_QTY, B.CONVERTED
FROM TEST A
CROSS APPLY
(VALUES
   (REQ_QTY1, CONVERTED1),
 (REQ_QTY2, CONVERTED2),
 (REQ_QTY3, CONVERTED3),
......
 (REQ_QTY31, CONVERTED31)
 )B (REQ_QTY, CONVERTED)

我找到的唯一方法是使用带内连接的嵌套选择

SELECT A.YEAR, A.MONTH,  A.DAY_OF_MONTH,  A.ITEM,A.REQ_QTY, D.CONVERTED FROM
  (SELECT YEAR, MONTH, ITEM, SUBSTRING(DAY_OF_MONTH,8,2) AS DAY_OF_MONTH, REQ_QTY FROM TEST 
  UNPIVOT
     (REQ_QTY FOR DAY_OF_MONTH IN ([REQ_QTY1],[REQ_QTY2],[REQ_QTY3],......[REQ_QTY30],[REQ_QTY31])
     ) B
  ) A
  INNER JOIN (SELECT YEAR, MONTH, ITEM, SUBSTRING(DAY_OF_MONTH,10,2) AS DAY_OF_MONTH, CONVERTED FROM TEST 
  UNPIVOT
     (CONVERTED FOR DAY_OF_MONTH IN ([CONVERTED1],[CONVERTED2],[CONVERTED3],....[CONVERTED30],[CONVERTED31])
     ) C
  ) D
  ON D.YEAR = A.YEAR AND D.MONTH = A.MONTH AND D.ITEM = A.ITEM AND D.DAY_OF_MONTH = A.DAY_OF_MONTH

有没有办法使用CROSS APPLY然后输出DAY_OF_MONTH?

2 个答案:

答案 0 :(得分:0)

这不是CROSS APPLY的解决方案,但它肯定会使它更快一点,因为它使用更简单的方法和更简单的执行计划。

SQL Fiddle

MS SQL Server 2008架构设置

CREATE TABLE Test_Table([YEAR] INT, [MONTH] INT, [ITEM] INT,  REQ_QTY1 INT
       , REQ_QTY2 INT ,REQ_QTY3 INT , CONVERTED1 INT, CONVERTED2 INT, CONVERTED3 INT)
INSERT INTO Test_Table VALUES 
( 2015 ,  1 , 1 , 10 , 20 , 30 , 100 , 200 , 300),
( 2015 ,  2 , 1 , 10 , 20 , 30 , 100 , 200 , 300), 
( 2015 ,  3 , 1 , 10 , 20 , 30 , 100 , 200 , 300)

查询1

SELECT *
FROM 
 (
    SELECT [YEAR] 
          ,[MONTH] 
          ,ITEM
          ,Vals
          ,CASE WHEN LEFT(N,3) = 'REQ' THEN SUBSTRING(N,8 ,2)
                WHEN LEFT(N,3) = 'CON' THEN SUBSTRING(N,10,2)
           END AS Day_Of_Month
          ,CASE WHEN LEFT(N,3) = 'REQ' THEN LEFT(N,7)
                WHEN LEFT(N,3) = 'CON' THEN LEFT(N,9)
           END AS Tran_Type
    FROM Test_Table t
      UNPIVOT (Vals FOR N IN ([REQ_QTY1],[REQ_QTY2],[REQ_QTY3],
                                            [CONVERTED1],[CONVERTED2],[CONVERTED3]))up
 )t2
PIVOT (SUM(Vals)
       FOR Tran_Type
       IN (REQ_QTY, CONVERTED))p  

<强> Results

| YEAR | MONTH | ITEM | Day_Of_Month | REQ_QTY | CONVERTED |
|------|-------|------|--------------|---------|-----------|
| 2015 |     1 |    1 |            1 |      10 |       100 |
| 2015 |     1 |    1 |            2 |      20 |       200 |
| 2015 |     1 |    1 |            3 |      30 |       300 |
| 2015 |     2 |    1 |            1 |      10 |       100 |
| 2015 |     2 |    1 |            2 |      20 |       200 |
| 2015 |     2 |    1 |            3 |      30 |       300 |
| 2015 |     3 |    1 |            1 |      10 |       100 |
| 2015 |     3 |    1 |            2 |      20 |       200 |
| 2015 |     3 |    1 |            3 |      30 |       300 |

答案 1 :(得分:0)

好吧,我找到了一种使用CROSS APPLY的方法,但我没有采用子字符串,而是基本上用硬编码的日子。效果很好,所以...

SELECT A.YEAR, A.MONTH, A.ITEM, B.DAY_OF_MONTH, B.REQ_QTY, B.CONVERTED
FROM TEST A
CROSS APPLY
(
  VALUES
  ('01', REQ_QTY1, CONVERTED1),
  ('02', REQ_QTY2, CONVERTED2),
  ('03', REQ_QTY3, CONVERTED3),
  ('04', REQ_QTY4, CONVERTED4),
   ......
  ('31', REQ_QTY31, CONVERTED31)
  ) B (DAY_OF_MONTH, REQ_QTY, CONVERTED)