我有一个带有这些值的表phone
emplid type phone
1 HOME 23452
2 HOME 15284
2 BUSN 25523
3 HOME 26542
我想让每个人都使用他的HOME和BUSN电话。如果他没有BUSN电话,则必须为空。所以我的结果必须是:
emplid type phone
1 HOME 23452
2 HOME 15284
2 BUSN 25523
3 HOME 26542
1 BUSN null
3 BUSN null
我试图加入一个虚拟表
(select 'HOME'as typ from dual
union select 'HOM2' from dual )
但是它没有给我想要的结果。我不知道如何将其与我的phone
表一起加入
答案 0 :(得分:5)
许多版本以前,Oracle仅为这种问题引入了分区外连接。 https://docs.oracle.com/cd/E11882_01/server.112/e25555/tdpdw_sql.htm#TDPDW0072
您确实需要一个包含各种类型的表。或者,您可以尝试动态创建它。另外,您需要外部联接的“ partition”子句。该代码显示在下面代码的ALL CAPS中(因此可以轻松找到它)。
作为单独的,不相关的内容,在我创建的“ helper”子查询中,它代替了实际的“类型”表,我还创建了一个ORD列,用于排序。仅当您要始终在主查询中的BUSN编号之前始终显示HOME编号时才需要这样做。当然,还有其他方法可以达到相同的结果,但是由于无论如何我们都创建了一个辅助子查询,因此基本上不需要额外的费用就可以得到它。
with
phone(emplid, type, phone) as (
select 1, 'HOME', 23452 from dual union all
select 2, 'HOME', 15284 from dual union all
select 2, 'BUSN', 25523 from dual union all
select 3, 'HOME', 26542 from dual
)
-- end of sample data (for testing only, not part of the actual query)
select p.emplid, h.type, p.phone
from (
select 'HOME' as type, 1 as ord from dual union all
select 'BUSN' , 2 from dual
) h
left outer join phone p PARTITION BY (EMPLID)
on h.type = p.type
order by p.emplid, h.ord
;
EMPLID TYPE PHONE
---------- ---- ----------
1 HOME 23452
1 BUSN
2 HOME 15284
2 BUSN 25523
3 HOME 26542
3 BUSN
答案 1 :(得分:1)
您需要获取所有可能的emplid
值并与所有可能的type
值交叉联接,然后使用外部联接查看实际存在的那些。
例如,如果您希望完全基于phone
表中的其他数据,则可以使用内联视图获得前两列的不同值:
-- CTE for your sample data
with phone (emplid, type, phone) as (
select 1, 'HOME', 23452 from dual
union all select 2, 'HOME', 15284 from dual
union all select 2, 'BUSN', 25523 from dual
union all select 3, 'HOME', 26542 from dual
)
-- actual query
select e.emplid, t.type, p.phone
from (select distinct emplid from phone) e
cross join (select distinct type from phone) t
left join phone p on p.emplid = e.emplid and p.type = t.type;
EMPLID TYPE PHONE
---------- ---- ----------
1 HOME 23452
2 HOME 15284
2 BUSN 25523
3 HOME 26542
3 BUSN
1 BUSN
但是您可能真的想从一个雇员表中获取可能的emplid
值-在这种情况下,即使他们根本没有电话记录,您也会看到所有雇员的空值;并且您可能想从其他表中获取可能的type
值,或对列表进行硬编码:
select e.emplid, t.type, p.phone
from (select distinct emplid from phone) e -- or more likely from a separate employee table
cross join (select 'HOME' as type from dual union all select 'HOM2' from dual) t
left join phone p on p.emplid = e.emplid and p.type = t.type;
EMPLID TYPE PHONE
---------- ---- ----------
1 HOME 23452
2 HOME 15284
3 HOME 26542
1 HOM2
2 HOM2
3 HOM2
即使您的样本数据中根本没有使用'HOM2'
值,我仍然坚持使用;但是如您所见,您也会在所有员工ID的名称中得到空条目。
答案 2 :(得分:0)
您尝试的是正确的方法。只是另一张桌子
SELECT PhoneTypes.EmplID, PhoneTypes.Type, Phone
FROM Phone
RIGHT OUTER JOIN (SELECT Distinct emplid, T.Type FROM Phone, (select 'HOME' FROM DUAL as type union select 'HOM2' FROM DUAL union select 'BUSN' FROM DUAL) T) PhoneTypes
ON Phone.type=PhoneTypes.Type
答案 3 :(得分:0)
尝试这样。我认为这与您的方法类似
select t.* from Phone t
left outer join
(
select 'HOME'as typ from dual
union select 'HOM2' from dual ) t2
on typ = type
答案 4 :(得分:0)
尝试一下
with
phone as (
select 1 as emplid, 'HOME' as type, '23452' as phone from dual union
select 2, 'HOME', '15284' from dual union
select 2,'BUSN','25523' from dual union
select 3,'HOME','26542' from dual),
types as (
select distinct type from phone
)
select phone.emplid, types.type, phone.phone
from types
left join phone partition by (emplid)
on phone.type = types.type
答案 5 :(得分:0)
一种选择是将逻辑与not in
with phone(emplid, type, phone) as
(
select 1, 'HOME', 23452 from dual union all
select 2, 'HOME', 15284 from dual union all
select 2, 'BUSN', 25523 from dual union all
select 3, 'HOME', 26542 from dual
)
select * from phone
union all
select emplid, 'BUSN', null
from phone
where emplid not in
( select emplid
from phone p
where type = 'BUSN'
and p.emplid = emplid );
EMPLID TYPE PHONE
------ ---- -----
1 HOME 23452
2 HOME 15284
2 BUSN 25523
3 HOME 26542
3 BUSN NULL
1 BUSN NULL