數(shù)據(jù)表示例:
從事內(nèi)江服務(wù)器托管,服務(wù)器租用,云主機,網(wǎng)頁空間,國際域名空間,CDN,網(wǎng)絡(luò)代維等服務(wù)。
假設(shè)要將name值作為行,course值作為列,轉(zhuǎn)換后效果為:
對應(yīng)的SQL如下:
方法1:使用表連接
SELECT DISTINCT a.name,
(SELECT score FROM grade b WHEREa.name=b.name AND b.course='語文')?AS?'語文',
(SELECT score FROM grade b WHEREa.name=b.name AND b.course='數(shù)學(xué)')?AS?'數(shù)學(xué)',
(SELECT score FROM grade b WHEREa.name=b.name AND b.course='英語')?AS?'英語'
FROM grade a
方法2:使用分組
SELECT name,
SUM(CASE?course WHEN?'語文'?THEN score END)?AS?'語文',
SUM(CASE?course WHEN?'數(shù)學(xué)'?THEN score END)?AS?'數(shù)學(xué)',
SUM(CASE?course WHEN?'英語'?THEN score END)?AS?'英語'
FROM grade GROUP BY name
行轉(zhuǎn)列的準(zhǔn)則就是通過主鍵進(jìn)行分組,之后對行其它字段加上sum()、max()、count()函數(shù),里邊用decode()這類函數(shù)進(jìn)行處理,總之分組不要用到他就成。
樓主這種 典型的行列轉(zhuǎn)換問題。
Oracle 一般就通過 DECODE 或者 CASE WHEN 來處理。
SQL CREATE TABLE TEST_YLX (
2 name VARCHAR2(2),
3 zfname VARCHAR2(6),
4 tdate DATE
5 );
Table created.
SQL
SQL INSERT INTO TEST_YLX VALUES ('A', 'size1', TO_DATE('2010-02-01', 'YYYY-MM-D
D') );
1 row created.
SQL INSERT INTO TEST_YLX VALUES ('A', 'size2', TO_DATE('2010-02-01', 'YYYY-MM-D
D') );
1 row created.
SQL INSERT INTO TEST_YLX VALUES ('B', 'size1', TO_DATE('2010-02-01', 'YYYY-MM-D
D') );
1 row created.
SQL INSERT INTO TEST_YLX VALUES ('C', 'size3', TO_DATE('2010-02-01', 'YYYY-MM-D
D') );
1 row created.
SQL
SQL SELECT
2 name,
3 SUM ( DECODE(zfname, 'size1', 1, 0) ) AS size1,
4 SUM ( DECODE(zfname, 'size2', 1, 0) ) AS size2,
5 SUM ( CASE WHEN(zfname = 'size3') THEN 1
6 ELSE 0
7 END
8 ) AS size3
9 FROM
10 test_ylx
11 GROUP BY
12 name;
NAME SIZE1 SIZE2 SIZE3
---- ---------- ---------- ----------
A 1 1 0
B 1 0 0
C 0 0 1
SQL
上面的例子中, size1 和 size2 是用 DECODE
size3 用 CASE WHEN
看具體情況需要,而使用。
========================================
唯一麻煩的是
這個SQL, 需要預(yù)先知道, size1 size2 size3 這些信息
如果表中新增加了 size4 , 需要修改 SQL 語句。
如果你要做轉(zhuǎn)換查詢,真心勸你不要這么干,我的寫法很麻煩,一張表不停的查詢,邏輯讀肯定搞得要死。
如果是往下面這張表灌數(shù),那么可以寫循環(huán),慢慢來一行對應(yīng)一列,可以根據(jù)表的列和數(shù)據(jù)的對應(yīng)關(guān)系往里面灌,這個相對簡單些。
我的寫法大概是子查詢+union
all
上面為a表
那么就寫為select
‘第一季度'
銷售額,(select
第一季度銷售額
from
a
where
產(chǎn)品名稱='奶酪')奶酪,(select
第一季度銷售額
from
a
where
產(chǎn)品名稱='啤酒')
from
dual
union
all
還像上面那么寫,寫第二季度
union
all
第三季度
union
all
第四季度
一張表重讀查詢8次,如果表很大,我估計機器會宕掉的。
因為單獨從一列來看也可以理解為列轉(zhuǎn)行,所以用case
when寫也可以,這么寫似乎讀取的次數(shù)會少些,不過要用到group
by分組,天知道二者最后誰的消耗大。不過如果表很大的話,還是那句話,建議新建表然后灌數(shù),這么直接查,真的會死掉的。
以上為個人建議,如果找到什么好寫法,也可以研究下。
如果“站名”、“條碼”、“時間”都是一樣的話,可以這么寫:
with
t_temp as (select row_number() over (partition by station_name order by param_name asc) id, t.* from t),
t_temp1 as (select * from t_temp where id = 1),
t_temp2 as (select * from t_temp where id = 2),
t_temp3 as (select * from t_temp where id = 3)
select '站名' col1, '條碼' col2, t_temp1.參數(shù)名 col3, t_temp2.參數(shù)名 col4, t_temp3.參數(shù)名 col5, '時間' col6
from t_temp1, t_temp2, t_temp3
where t_temp1.站名 = t_temp2.站名
and t_temp2.站名 = t_temp3.站名
union all
select t_temp1.站名, t_temp1.條碼, to_char(t_temp1.數(shù)值), to_char(t_temp2.數(shù)值), to_char(t_temp3.數(shù)值), to_char(t_temp1.時間)
from t_temp1, t_temp2, t_temp3
where t_temp1.站名 = t_temp2.站名
and t_temp2.站名 = t_temp3.站名
可用union all來實現(xiàn)。
如test表中數(shù)據(jù)如下:
現(xiàn)要將id為3的一條按列顯示,可用如下語句:
select?to_char(id)?str?from?test?where?id=3
union?all
select?name?from?test?where?id=3;
查詢結(jié)果: