[SQL]使用UNPIVOT來取代CASE WHEN

  • 25713
  • 0
  • SQL
  • 2013-09-02

[SQL]使用UNPIVOT來取代CASE WHEN

有朋友問「如果column name與另外一個column的內容是有關聯的,如果通過sql 查問」,直接看圖比較清楚,如下,

image

 

測試Script如下,


USE tempdb
GO

--drop table #t1

CREATE TABLE #t1
(
client VARCHAR(10),
pay_level INT,
pay_lv_1_cost INT,
pay_lv_2_cost INT,
pay_lv_3_cost int
);

INSERT INTO #t1 ( client ,
          pay_level ,
          pay_lv_1_cost ,
          pay_lv_2_cost ,
          pay_lv_3_cost
        )
VALUES  ( 'client1' , -- client - varchar(10)
          1, -- pay_level - int
          10 , -- pay_lv_1 - int
          12 , -- pay_lv_2 - int
          14  -- pay_lv_3 - int
        )


INSERT INTO #t1 ( client ,
          pay_level ,
          pay_lv_1_cost ,
          pay_lv_2_cost ,
          pay_lv_3_cost
        )
VALUES  ( 'client2' , -- client - varchar(10)
          3, -- pay_level - int
          21 , -- pay_lv_1 - int
          22 , -- pay_lv_2 - int
          23  -- pay_lv_3 - int
        )

INSERT INTO #t1 ( client ,
          pay_level ,
          pay_lv_1_cost ,
          pay_lv_2_cost ,
          pay_lv_3_cost
        )
VALUES  ( 'client3' , -- client - varchar(10)
          2, -- pay_level - int
          30 , -- pay_lv_1 - int
          32 , -- pay_lv_2 - int
          33  -- pay_lv_3 - int
        )

 

要的結果如下,


--使用CASE WHEN
SELECT client,
CASE pay_level 
	WHEN 1 THEN pay_lv_1_cost 
	WHEN 2 THEN pay_lv_2_cost
	WHEN 3 THEN pay_lv_3_cost
	ELSE -99 END AS PaylvCost
FROM #t1;

image

 

所以如果不想使用CASE WHEN的話,可以改用 UNPIVOT ,如下,


--使用UNPIVOT + WHERE
SELECT *
FROM 
   (SELECT *
   FROM #t1) p
UNPIVOT
   (PaylvCost FOR pay_lv IN 
      (pay_lv_1_cost, pay_lv_2_cost, pay_lv_3_cost)
)AS unpvt
--將CASE WHEN的判斷,改成 CAST(RIGHT(pay_lv, 1) AS INT)  =  pay_level;
WHERE CAST(substring(pay_lv, 8, 1) AS INT)  =  pay_level;

image

 

2013/09/02 補充使用動態的方式,


--使用動態
DECLARE @in_columns VARCHAR (MAX)
SELECT @in_columns = COALESCE (@in_columns + ',[' +  'pay_lv_' +  RTRIM(T.pay_level) + '_cost]', '[' + 'pay_lv_' +  RTRIM(T.pay_level) + '_cost]')
FROM  (SELECT DISTINCT pay_level FROM  #t1) T

PRINT @in_columns;

EXEC('SELECT * FROM 
   (SELECT *
   FROM #t1) p
UNPIVOT
   (PaylvCost FOR pay_lv IN 
      (' + @in_columns +  ')
)AS unpvt
--取出 pay_lv_1_cost中的數值
WHERE CAST(substring(pay_lv, 8, len(pay_lv) - 7 - CHARINDEX(''_'', REVERSE(pay_lv)) ) AS INT)  =  pay_level;');

不知其他先進是否有其他的方法呢?

Hi, 

亂馬客Blog已移到了 「亂馬客​ : Re:從零開始的軟體開發生活

請大家繼續支持 ^_^