Oracle SQL 从多个自连接中删除不相同的重复项
Oracl SQL remove non-identical duplicates from multiple self join
我有一个 table 多人在同一个套房
我需要在套房上进行匹配,然后将每个人与他们的室友列表一起显示为第一个 ID。
因为他们不止两个,我 运行 遇到多个结果的情况,其中第一个 ID 被多次列出,室友的顺序不同,或者我只能带回一行4个ID
示例:
我有一个 table 这样的:
Table Name: ROOM_LIST
ID | BUILDING | SUITE | ROOM
01 | BU_1 | SU_1 | RO_1
02 | BU_1 | SU_1 | RO_2
03 | BU_1 | SU_1 | RO_3
04 | BU_1 | SU_1 | RO_4
05 | BU_1 | SU_2 | RO_1
06 | BU_1 | SU_2 | RO_2
07 | BU_2 | SU_1 | RO_1
08 | BU_2 | SU_1 | RO_2
我试过这样的查询:
select A.ID as Primary,
B.ID as Roomate_1,
C.ID as Roomate_2,
D.ID as Roomate_3,
A.BUILDING as Building,
A.SUITE As Suite,
A.ROOM As Room
from ROOM_LIST A
Left Join ROOM_LIST B on A.BUILDING = B.BUILDING and A.SUITE = B.SUITE
Left Join ROOM_LIST C on A.BUILDING = C.BUILDING and A.SUITE = C.SUITE
Left Join ROOM_LIST D on A.BUILDING = D.BUILDING and A.SUITE = D.SUITE
where A.ID > B.ID
and A.ID > C.ID
and A.ID > D.ID
and B.ID > C.ID
and B.ID > D.ID
and C.ID > D.ID
order by Primary,Roomate_1,Roomate_2,Roomate_3,Building,Suite,Room;
这消除了额外的重复项,但我每个套件只得到一行,而不是将每个 ID 作为主 ID 的一行。
也尝试了一个类似的,但使用 <> 或 != 而不是 > 然后我得到多个重复项,其中一个 ID 作为第一个,但第二个、第三个和第四个是互换的,所以它们在技术上不是重复项。
这就是为什么我说 "non identical" 重复 :)
我的最终结果如下所示:
| Primary | Roomate_1 | Roomate_2 | Roomate_3 | Building | Suite | Room
| 01 | 02 | 03 | 04 | BU_1 | SU_1 | RO_1
| 02 | 03 | 04 | 01 | BU_1 | SU_1 | RO_2
| 03 | 04 | 01 | 02 | BU_1 | SU_1 | RO_3
| 04 | 01 | 02 | 03 | BU_1 | SU_1 | RO_4
| 05 | 06 | Null | Null | BU_1 | SU_2 | RO_1
| 06 | 05 | Null | Null | BU_1 | SU_2 | RO_2
我在 select 语句或 from 中尝试了使用不同子 select 的多个查询,但我似乎无法将每个 ID 作为主 ID 归结为一个结果。我已经研究过做一个数据透视表,但是(我的理解)只有当我有相同的 id 有多个结果并且我想将多个结果转换成列时才有效。
想过联合,但不知道如何跨联合查询?如果那是一件事
如有任何帮助,我们将不胜感激
编辑:下面的解决方案仅适用于 12C,但我需要一个 11G 解决方案:
with dt as (
select 01 id , 'BU_1' building, 'SU_1' suite ,'RO_1' room from dual union all
select 02 id , 'BU_1' building, 'SU_1' suite ,'RO_2' room from dual union all
select 03 id , 'BU_1' building, 'SU_1' suite ,'RO_3' room from dual union all
select 04 id , 'BU_1' building, 'SU_1' suite ,'RO_4' room from dual union all
select 05 id , 'BU_1' building, 'SU_2' suite ,'RO_1' room from dual union all
select 06 id , 'BU_1' building, 'SU_2' suite ,'RO_2' room from dual union all
select 07 id , 'BU_2' building, 'SU_1' suite ,'RO_1' room from dual union all
select 08 id , 'BU_2' building, 'SU_1' suite ,'RO_2' room from dual )
SELECT
A.ID as Primary,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite and b.ID != a.ID order by id ) where rn=1) Roomate_1,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite and b.ID != a.ID order by id ) where rn=2) Roomate_2,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite and b.ID != a.ID order by id ) where rn=3) Roomate_3,
a.BUILDING as Building,
A.SUITE As Suite,
A.ROOM As Room
FROM
dt a
order by Primary,Roomate_1,Roomate_2,Roomate_3,Building,Suite,Room
我在给定的答案之一中添加了以下内容:and b.ID != a.ID
并更改了 rn=2 to rn=1
以开始计数,因为 0
不确定性能影响。将需要进行分析,但给出的结果符合预期。
12c 答案。
with dt as (
select 01 id , 'BU_1' building, 'SU_1' suite ,'RO_1' room from dual union all
select 02 , 'BU_1' building, 'SU_1' suite ,'RO_2' room from dual union all
select 03 , 'BU_1' building, 'SU_1' suite ,'RO_3' room from dual union all
select 04, 'BU_1' building, 'SU_1' suite ,'RO_4' room from dual union all
select 05 , 'BU_1' building, 'SU_2' suite ,'RO_1' room from dual union all
select 06 , 'BU_1' building, 'SU_2' suite ,'RO_2' room from dual union all
select 07 , 'BU_2' building, 'SU_1' suite ,'RO_1' room from dual union all
select 08 , 'BU_2' building, 'SU_1' suite ,'RO_2' room from dual )
SELECT
A.ID as Primary,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite order by id ) where rn=2) Roomate_1,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite order by id ) where rn=3) Roomate_2,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite order by id ) where rn=4) Roomate_3,
a.BUILDING as Building,
A.SUITE As Suite,
A.ROOM As Room
FROM
dt a
order by Primary,Roomate_1,Roomate_2,Roomate_3,Building,Suite,Room
11g 答案。我不确定在 rooommate1 到 roomate3 列中需要多少数据排序。
WITH dt as (
select 01 id , 'BU_1' building, 'SU_1' suite ,'RO_1' room from dual union all
select 02 id , 'BU_1' building, 'SU_1' suite ,'RO_2' room from dual union all
select 03 id , 'BU_1' building, 'SU_1' suite ,'RO_3' room from dual union all
select 04 id , 'BU_1' building, 'SU_1' suite ,'RO_4' room from dual union all
select 05 id , 'BU_1' building, 'SU_2' suite ,'RO_1' room from dual union all
select 06 id , 'BU_1' building, 'SU_2' suite ,'RO_2' room from dual union all
select 07 id , 'BU_2' building, 'SU_1' suite ,'RO_1' room from dual union all
select 08 id , 'BU_2' building, 'SU_1' suite ,'RO_2' room from dual ),
joindrslt AS (
SELECT a.*, b.id roommate,
ROW_NUMBER() OVER(PARTITION BY a.suite, a.building, a.room ORDER BY b.id ) AS ri
FROM
dt a
JOIN dt b ON a.building = b.building AND a.suite = b.suite AND b.id != a.id
ORDER BY b.id
)
SELECT ID Primary,
roomate_1,
roomate_2,
roomate_3,
Building,Suite,
Room FROM
(
SELECT
*
FROM
joindrslt PIVOT (
MAX ( roommate )
FOR ri
IN ( 1 AS roomate_1, 2 AS roomate_2, 3 AS roomate_3 )
)
)
ORDER BY
Primary,Roomate_1,Roomate_2,Roomate_3,Building,Suite,Room
我有一个 table 多人在同一个套房 我需要在套房上进行匹配,然后将每个人与他们的室友列表一起显示为第一个 ID。
因为他们不止两个,我 运行 遇到多个结果的情况,其中第一个 ID 被多次列出,室友的顺序不同,或者我只能带回一行4个ID
示例:
我有一个 table 这样的:
Table Name: ROOM_LIST
ID | BUILDING | SUITE | ROOM
01 | BU_1 | SU_1 | RO_1
02 | BU_1 | SU_1 | RO_2
03 | BU_1 | SU_1 | RO_3
04 | BU_1 | SU_1 | RO_4
05 | BU_1 | SU_2 | RO_1
06 | BU_1 | SU_2 | RO_2
07 | BU_2 | SU_1 | RO_1
08 | BU_2 | SU_1 | RO_2
我试过这样的查询:
select A.ID as Primary,
B.ID as Roomate_1,
C.ID as Roomate_2,
D.ID as Roomate_3,
A.BUILDING as Building,
A.SUITE As Suite,
A.ROOM As Room
from ROOM_LIST A
Left Join ROOM_LIST B on A.BUILDING = B.BUILDING and A.SUITE = B.SUITE
Left Join ROOM_LIST C on A.BUILDING = C.BUILDING and A.SUITE = C.SUITE
Left Join ROOM_LIST D on A.BUILDING = D.BUILDING and A.SUITE = D.SUITE
where A.ID > B.ID
and A.ID > C.ID
and A.ID > D.ID
and B.ID > C.ID
and B.ID > D.ID
and C.ID > D.ID
order by Primary,Roomate_1,Roomate_2,Roomate_3,Building,Suite,Room;
这消除了额外的重复项,但我每个套件只得到一行,而不是将每个 ID 作为主 ID 的一行。
也尝试了一个类似的,但使用 <> 或 != 而不是 > 然后我得到多个重复项,其中一个 ID 作为第一个,但第二个、第三个和第四个是互换的,所以它们在技术上不是重复项。
这就是为什么我说 "non identical" 重复 :)
我的最终结果如下所示:
| Primary | Roomate_1 | Roomate_2 | Roomate_3 | Building | Suite | Room
| 01 | 02 | 03 | 04 | BU_1 | SU_1 | RO_1
| 02 | 03 | 04 | 01 | BU_1 | SU_1 | RO_2
| 03 | 04 | 01 | 02 | BU_1 | SU_1 | RO_3
| 04 | 01 | 02 | 03 | BU_1 | SU_1 | RO_4
| 05 | 06 | Null | Null | BU_1 | SU_2 | RO_1
| 06 | 05 | Null | Null | BU_1 | SU_2 | RO_2
我在 select 语句或 from 中尝试了使用不同子 select 的多个查询,但我似乎无法将每个 ID 作为主 ID 归结为一个结果。我已经研究过做一个数据透视表,但是(我的理解)只有当我有相同的 id 有多个结果并且我想将多个结果转换成列时才有效。
想过联合,但不知道如何跨联合查询?如果那是一件事
如有任何帮助,我们将不胜感激
编辑:下面的解决方案仅适用于 12C,但我需要一个 11G 解决方案:
with dt as (
select 01 id , 'BU_1' building, 'SU_1' suite ,'RO_1' room from dual union all
select 02 id , 'BU_1' building, 'SU_1' suite ,'RO_2' room from dual union all
select 03 id , 'BU_1' building, 'SU_1' suite ,'RO_3' room from dual union all
select 04 id , 'BU_1' building, 'SU_1' suite ,'RO_4' room from dual union all
select 05 id , 'BU_1' building, 'SU_2' suite ,'RO_1' room from dual union all
select 06 id , 'BU_1' building, 'SU_2' suite ,'RO_2' room from dual union all
select 07 id , 'BU_2' building, 'SU_1' suite ,'RO_1' room from dual union all
select 08 id , 'BU_2' building, 'SU_1' suite ,'RO_2' room from dual )
SELECT
A.ID as Primary,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite and b.ID != a.ID order by id ) where rn=1) Roomate_1,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite and b.ID != a.ID order by id ) where rn=2) Roomate_2,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite and b.ID != a.ID order by id ) where rn=3) Roomate_3,
a.BUILDING as Building,
A.SUITE As Suite,
A.ROOM As Room
FROM
dt a
order by Primary,Roomate_1,Roomate_2,Roomate_3,Building,Suite,Room
我在给定的答案之一中添加了以下内容:and b.ID != a.ID
并更改了 rn=2 to rn=1
以开始计数,因为 0
不确定性能影响。将需要进行分析,但给出的结果符合预期。
12c 答案。
with dt as (
select 01 id , 'BU_1' building, 'SU_1' suite ,'RO_1' room from dual union all
select 02 , 'BU_1' building, 'SU_1' suite ,'RO_2' room from dual union all
select 03 , 'BU_1' building, 'SU_1' suite ,'RO_3' room from dual union all
select 04, 'BU_1' building, 'SU_1' suite ,'RO_4' room from dual union all
select 05 , 'BU_1' building, 'SU_2' suite ,'RO_1' room from dual union all
select 06 , 'BU_1' building, 'SU_2' suite ,'RO_2' room from dual union all
select 07 , 'BU_2' building, 'SU_1' suite ,'RO_1' room from dual union all
select 08 , 'BU_2' building, 'SU_1' suite ,'RO_2' room from dual )
SELECT
A.ID as Primary,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite order by id ) where rn=2) Roomate_1,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite order by id ) where rn=3) Roomate_2,
( select id from (select id,rownum rn from dt b where a.building = b.building AND a.suite = b.suite order by id ) where rn=4) Roomate_3,
a.BUILDING as Building,
A.SUITE As Suite,
A.ROOM As Room
FROM
dt a
order by Primary,Roomate_1,Roomate_2,Roomate_3,Building,Suite,Room
11g 答案。我不确定在 rooommate1 到 roomate3 列中需要多少数据排序。
WITH dt as (
select 01 id , 'BU_1' building, 'SU_1' suite ,'RO_1' room from dual union all
select 02 id , 'BU_1' building, 'SU_1' suite ,'RO_2' room from dual union all
select 03 id , 'BU_1' building, 'SU_1' suite ,'RO_3' room from dual union all
select 04 id , 'BU_1' building, 'SU_1' suite ,'RO_4' room from dual union all
select 05 id , 'BU_1' building, 'SU_2' suite ,'RO_1' room from dual union all
select 06 id , 'BU_1' building, 'SU_2' suite ,'RO_2' room from dual union all
select 07 id , 'BU_2' building, 'SU_1' suite ,'RO_1' room from dual union all
select 08 id , 'BU_2' building, 'SU_1' suite ,'RO_2' room from dual ),
joindrslt AS (
SELECT a.*, b.id roommate,
ROW_NUMBER() OVER(PARTITION BY a.suite, a.building, a.room ORDER BY b.id ) AS ri
FROM
dt a
JOIN dt b ON a.building = b.building AND a.suite = b.suite AND b.id != a.id
ORDER BY b.id
)
SELECT ID Primary,
roomate_1,
roomate_2,
roomate_3,
Building,Suite,
Room FROM
(
SELECT
*
FROM
joindrslt PIVOT (
MAX ( roommate )
FOR ri
IN ( 1 AS roomate_1, 2 AS roomate_2, 3 AS roomate_3 )
)
)
ORDER BY
Primary,Roomate_1,Roomate_2,Roomate_3,Building,Suite,Room