实施例: 表结构:
EMP_ID SAL_MONTHWISE(JAN) SAL_MONTHWISE(FEB) SAL_MONTHWISE(MAR)
1 10000 15000 8000
2 20000 2000 10000
3 50000 60000 40000
需要新格式:按每位员工的工资增加顺序
EMP_ID SAL_MONTH1 SAL_MONTH2 SAL_MONTH3
1 8000 10000 15000
2 2000 10000 20000
3 40000 50000 60000
提前致谢!!
答案 0 :(得分:2)
对于所需输出中的第一列和最后一列,使用 LEAST 和 GREATEST 功能很容易。对于其他列,我会使用 CASE 构造。
编辑 CASE应该将WHEN条件设为AND而不是OR。
SQL> WITH data AS
2 ( SELECT 1 emp_id, 10000 jan, 15000 feb, 8000 mar FROM dual
3 UNION ALL
4 SELECT 2 , 20000 , 2000 , 10000 FROM dual
5 UNION ALL
6 SELECT 3 , 50000 , 60000 , 40000 FROM dual
7 )
8 SELECT emp_id,
9 least(jan, feb, mar) jan,
10 CASE
11 WHEN jan > least(jan, feb, mar)
12 AND jan < greatest(jan, feb, mar)
13 THEN jan
14 WHEN feb > least(jan, feb, mar)
15 AND feb < greatest(jan, feb, mar)
16 THEN feb
17 WHEN mar > least(jan, feb, mar)
18 AND mar < greatest(jan, feb, mar)
19 THEN mar
20 END feb,
21 greatest(jan, feb, mar) mar
22 FROM DATA
23 /
EMP_ID JAN FEB MAR
---------- ---------- ---------- ----------
1 8000 10000 15000
2 2000 10000 20000
3 40000 50000 60000
SQL>
答案 1 :(得分:2)
可以使用三列以上的更通用的解决方案是将列拆分为单独的行,计算出值应该处于什么顺序,然后将它们转回到列中。从11g开始,你可以用
来解开select * from your_table
unpivot (sal for month in (sal_jan as 'Jan', sal_feb as 'Feb', sal_mar as 'Mar'));
给你:
EMP_ID MONTH SAL
---------- ----- ----------
1 Jan 10000
1 Feb 15000
1 Mar 8000
2 Jan 20000
2 Feb 2000
2 Mar 10000
3 Jan 50000
3 Feb 60000
3 Mar 40000
您并不关心月份名称。然后按工资值添加行号伪列顺序:
select t.*, row_number() over (partition by emp_id order by sal) as rn
from your_table
unpivot (sal for month in (sal_jan as 'Jan', sal_feb as 'Feb', sal_mar as 'Mar')) t;
然后转回来:
select * from (
select t.emp_id, t.sal,
row_number() over (partition by emp_id order by sal) as rn
from your_table
unpivot (sal for month in (sal_jan as 'Jan', sal_feb as 'Feb', sal_mar as 'Mar')) t
)
pivot (max(sal) as sal for (rn) in (1 as "1", 2 as "2", 3 as "3"))
order by emp_id;
EMP_ID 1_SAL 2_SAL 3_SAL
---------- ---------- ---------- ----------
1 8000 10000 15000
2 2000 10000 20000
3 40000 50000 60000
SQL Fiddle demo。只需向pivot和unpivot部分的in
子句添加值对,就可以很容易地扩展更多列。
如果您使用的是早期版本 - 当您使用11g和10g标记问题时,这一点并不清楚 - 您必须手动取消转动和转动,这有点啰嗦; to unpivot:
with unpivot_data as (
select level as unpivot_rn from dual connect by level <= 3
)
select t.emp_id,
case ud.unpivot_rn
when 1 then t.sal_jan
when 2 then t.sal_feb
when 3 then t.sal_mar
end as sal
from t42 t
cross join unpivot_data ud;
...其中connect by
中的行数和case when
子句的数量是您拥有的列数;然后根据工资添加行号:
with unpivot_data as (
select level as unpivot_rn from dual connect by level <= 3
),
tmp_data as (
select t.emp_id,
case ud.unpivot_rn
when 1 then t.sal_jan
when 2 then t.sal_feb
when 3 then t.sal_mar
end as sal
from t42 t
cross join unpivot_data ud
)
select td.emp_id, td.sal,
row_number() over (partition by td.emp_id order by td.sal) as rn
from tmp_data td;
然后使用max(case ...)
和group by
with unpivot_data as (
select level as unpivot_rn from dual connect by level <= 3
),
tmp_data as (
select t.emp_id,
case ud.unpivot_rn
when 1 then t.sal_jan
when 2 then t.sal_feb
when 3 then t.sal_mar
end as sal
from your_table t
cross join unpivot_data ud
),
tmp_with_rn as (
select td.emp_id, td.sal,
row_number() over (partition by td.emp_id order by td.sal) as rn
from tmp_data td
)
select twr.emp_id,
max(case when twr.rn = 1 then twr.sal end) as month_1,
max(case when twr.rn = 2 then twr.sal end) as month_2,
max(case when twr.rn = 3 then twr.sal end) as month_3
from tmp_with_rn twr
group by twr.emp_id
order by emp_id;
EMP_ID MONTH_1 MONTH_2 MONTH_3
---------- ---------- ---------- ----------
1 8000 10000 15000
2 2000 10000 20000
3 40000 50000 60000
SQL Fiddle demo。如果列数增加,现在需要更改三个位置,但这仍然相当简单。