十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
数据表示例:
从事内江服务器托管,服务器租用,云主机,网页空间,国际域名空间,CDN,网络代维等服务。
假设要将name值作为行,course值作为列,转换后效果为:
对应的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='数学') AS '数学',
(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 '数学' THEN score END) AS '数学',
SUM(CASE course WHEN '英语' THEN score END) AS '英语'
FROM grade GROUP BY name
行转列的准则就是通过主键进行分组,之后对行其它字段加上sum()、max()、count()函数,里边用decode()这类函数进行处理,总之分组不要用到他就成。
楼主这种 典型的行列转换问题。
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, 需要预先知道, size1 size2 size3 这些信息
如果表中新增加了 size4 , 需要修改 SQL 语句。
如果你要做转换查询,真心劝你不要这么干,我的写法很麻烦,一张表不停的查询,逻辑读肯定搞得要死。
如果是往下面这张表灌数,那么可以写循环,慢慢来一行对应一列,可以根据表的列和数据的对应关系往里面灌,这个相对简单些。
我的写法大概是子查询+union
all
上面为a表
那么就写为select
‘第一季度'
销售额,(select
第一季度销售额
from
a
where
产品名称='奶酪')奶酪,(select
第一季度销售额
from
a
where
产品名称='啤酒')
from
dual
union
all
还像上面那么写,写第二季度
union
all
第三季度
union
all
第四季度
一张表重读查询8次,如果表很大,我估计机器会宕掉的。
因为单独从一列来看也可以理解为列转行,所以用case
when写也可以,这么写似乎读取的次数会少些,不过要用到group
by分组,天知道二者最后谁的消耗大。不过如果表很大的话,还是那句话,建议新建表然后灌数,这么直接查,真的会死掉的。
以上为个人建议,如果找到什么好写法,也可以研究下。
如果“站名”、“条码”、“时间”都是一样的话,可以这么写:
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.参数名 col3, t_temp2.参数名 col4, t_temp3.参数名 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.数值), to_char(t_temp2.数值), to_char(t_temp3.数值), to_char(t_temp1.时间)
from t_temp1, t_temp2, t_temp3
where t_temp1.站名 = t_temp2.站名
and t_temp2.站名 = t_temp3.站名
可用union all来实现。
如test表中数据如下:
现要将id为3的一条按列显示,可用如下语句:
select to_char(id) str from test where id=3
union all
select name from test where id=3;
查询结果: