1. 程式人生 > >sql應用行轉列與列轉行

sql應用行轉列與列轉行

一、行轉列例項:

場景:

今天運營人員讓我提取每個使用者在某種交易型別下每年的交易總金額。

表結構:

CREATE TABLE `ORDERS` (
  `ID` int(11) NOT NULL AUTO_INCREMENT,
  `USER_ID` varchar(10) COLLATE utf8_bin DEFAULT NULL COMMENT '使用者號',
  `TRADE_TYPE` varchar(10) COLLATE utf8_bin DEFAULT NULL COMMENT '交易型別(PAY.BANK付款到銀行、PAY.QUICK快捷支付、PAY.GATE閘道器支付)',
  `TRANS_AMOUNT` int(11) DEFAULT NULL COMMENT '交易金額',
  `TRANS_TIME` datetime DEFAULT NULL COMMENT '交易時間',
  PRIMARY KEY (`ID`)
);

測試資料如下


實現sql如下:

SELECT
USER_ID,
DATE_FORMAT(TRANS_TIME,'%Y'),
SUM(CASE TRADE_TYPE WHEN 'PAY.BANK' THEN TRANS_AMOUNT ELSE 0 END) AS '付款到銀行',
SUM(CASE TRADE_TYPE WHEN 'PAY.GATE' THEN TRANS_AMOUNT ELSE 0 END) AS '閘道器支付',
SUM(CASE TRADE_TYPE WHEN 'PAY.QUICK' THEN TRANS_AMOUNT ELSE 0 END) AS '快捷支付'
FROM
orders
GROUP BY
USER_ID,DATE_FORMAT(TRANS_TIME,'%Y');

執行結果:


分析:通過case when then else end 實現了行專列的功能,從而實現了需求。

二、列轉行例項

場景:

目前資料庫中存在一張表記錄了學生在某次考試中語文、數學、英語的分數。想要通過列轉行功能實現一行中只包含一科成績

表結構:

create table score(
id int not null primary KEY,
student_id int,
CN_SCORE INT, 
MATH_SCORE INT,
EN_SCORE INT
);

測試資料:


列轉行sql實現:



SELECT STUDENT_ID, '語文'  as course, cn_score AS score from score
UNION
SELECT STUDENT_ID, '數學'  as course, math_score AS score from score
UNION
SELECT STUDENT_ID, '英語'  as course, en_score AS score from score

執行結果:


總結:通過union或者union all 可以實現。但是要搞清楚union和union all的區別

1、對重複結果的處理:union在進行錶鏈接後會篩選掉重複的記錄,union all 不會取出重複記錄。

2、對排序的處理: union將會按照欄位的順序進行排序;union all 只是簡單的將兩個結果合併後返回。

3、效率上:很明顯union all 效率更高