ID | Type | Code
1 Purchase A1
1 Return B1
1 Exchange C1
2 Purchase D1
2 Return NULL
2 Exchange F1
3 Purchase G1
3 Return H1
3 Exchange I1
4 Purchase J1
4 Exchange K1
以上是样本数据。我想要回归的是:
ID | Type | Code
1 Purchase A1
1 Return B1
1 Exchange C1
3 Purchase G1
3 Return H1
3 Exchange I1
因此,如果某个字段在代码中为空,或者该ID不存在Purchase,Return和Exchange的值,则完全忽略该ID。然而,还有最后一步。我希望这些数据以这种方式转动:
ID | Purchase | Return | Exchange
1 A1 B1 C1
3 G1 H1 I1
我昨天问过这个没有枢轴部分,你可以在这里看到:
SQL query to return data only if ALL necessary columns are present and not NULL
但是我忘记了最后一部分。我试着玩excel但没有运气。我试图制作一个临时表但数据太大而无法做到这一点所以我想知道这是否可以在1 sql语句中完成?
我个人成功地使用了这个查询:
select t.*
from t
where 3 = (select count(distinct t2.type)
from t t2
where t2.id = t.id and
t2.type in ('Purchase', 'Exchange', 'Return') and
t2.Code is not null
);
那么我们如何调整它以包括枢轴部分。这可能吗?
答案 0 :(得分:2)
很容易。只需使用条件聚合:
select t.id,
max(case when type = 'Purchase' then code end) as Purchase,
max(case when type = 'Exchange' then code end) as Exchange,
max(case when type = 'Return' then code end) as Return
from t
where 3 = (select count(distinct t2.type)
from t t2
where t2.id = t.id and
t2.type in ('Purchase', 'Exchange', 'Return') and
t2.Code is not null
)
group by t.id;
在没有子查询的情况下使用having
来表达(在我看来)实际上更简单:
select t.id,
max(case when type = 'Purchase' then code end) as Purchase,
max(case when type = 'Exchange' then code end) as Exchange,
max(case when type = 'Return' then code end) as Return
from t
group by t.id
having max(case when type = 'Purchase' then code end) is not null and
max(case when type = 'Exchange' then code end) is not null and
max(case when type = 'Return' then code end) is not null;
许多数据库都允许:
having Purchase is not null and Exchange is not null and Return is not null
但Oracle不允许在having
子句中使用表别名。
答案 1 :(得分:1)
更新 - 根据问题评论中的讨论,我之前的查询有一个错误的假设(我从我认为在问题中的原始查询中看到的那个结转);我已经消除了这个不好的假设。
select id
, max(case when type='Purchase' then Code end) Purchase
, max(case when type='Return' then Code end) Return
, max(case when type='Exchange' then Code end) Exchange
from t
where code is not null
and type in ('Purchase', 'Return', 'Exchange')
group by id
having count(distinct type) = 3
答案 2 :(得分:0)
我将再次指出(正如我在你的其他线程中所做的那样)分析函数将更快地完成工作 - 它们需要只读取一次基表,并且没有显式或隐式连接。
with
test_data ( id, type, code ) as (
select 1, 'Purchase', 'A1' from dual union all
select 1, 'Return' , 'B1' from dual union all
select 1, 'Exchange', 'C1' from dual union all
select 2, 'Purchase', 'D1' from dual union all
select 2, 'Return' , null from dual union all
select 2, 'Exchange', 'F1' from dual union all
select 3, 'Purchase', 'G1' from dual union all
select 3, 'Return' , 'H1' from dual union all
select 3, 'Exchange', 'I1' from dual union all
select 4, 'Purchase', 'J1' from dual union all
select 4, 'Exchange', 'K1' from dual
)
-- end of test data; actual solution (SQL query) begins below this line
select id, purchase, return, exchange
from ( select id, type, code
from ( select id, type, code,
count( distinct case when type in ('Purchase', 'Return', 'Exchange')
then type end
) over (partition by id) as ct_type,
count( case when code is null then 1 end
) over (partition by id) as ct_code
from test_data
)
where ct_type = 3 and ct_code = 0
)
pivot ( min(code) for type in ('Purchase' as purchase, 'Return' as return,
'Exchange' as exchange)
)
;
输出:
ID PURCHASE RETURN EXCHANGE
--- -------- -------- --------
1 A1 B1 C1
3 G1 H1 I1
2 rows selected.