我正在尝试使用 vendor 表和 vendor_address 表中的多个字段从数据库中查找重复的供应商。事情是我做的内部联接越多,查询就越不会失去潜在的结果。虽然我没有在供应商ID中重复,但我希望找到类似的潜在供应商。
到目前为止,这是我的查询:
err
答案 0 :(得分:0)
似乎你的联接有点有趣,原因多于一个。首先,你有内部联接,这将消除所有所有重复迹象的东西 - 这是你不想要的东西。另外,你似乎在所有派生表上都有相同的别名oc - 这不会真的会飞到这里,而你也不会对此有所了解。
不是这样做,我建议你为每个复制标记重复基本查询 - 如下所示(我删除了same_address_nb和same_postal_nb字段,你会明白为什么):
select
o.vendor_id
,o.vndr_name_shrt_user
,O.COUNTRY
,O.VENDOR_NAME_SHORT
,B.POSTAL
,B.ADDRESS1
,OC.SAME_SHORT_NAME
,oc.SAME_USER_NUM
from VENDOR o
JOIN vendor_addr B ON o.VENDOR_ID = B.VENDOR_ID
WHERE O.COUNTRY ='CANADA'
AND B.COUNTY = 'CANADA'
AND ...
对于这些重复标记中的每一个,您将向上面显示的省略号添加嵌套查询,如下所示 - 使用vndr_name_shrt_user中的副本显示示例:
select
o.vendor_id
,o.vndr_name_shrt_user
,O.COUNTRY
,O.VENDOR_NAME_SHORT
,B.POSTAL
,B.ADDRESS1
,OC.SAME_SHORT_NAME
,oc.SAME_USER_NUM
,'SAME_USER_NUM' as duplicateFlag
from VENDOR o
JOIN vendor_addr B ON o.VENDOR_ID = B.VENDOR_ID
WHERE O.COUNTRY ='CANADA'
AND B.COUNTY = 'CANADA'
AND o.vndr_name_shrt_user in
(
SELECT
vndr_name_shrt_user
FROM VENDOR
WHERE COUNTRY = o.country
AND VENDOR_STATUS = 'A'
GROUP BY vndr_name_shrt_user
HAVING COUNT(*) > 1
)
您可以UNION ALL
将这些查询放在一起,然后查看所有重复项。
作为旁注,您在最后三个派生表中检查了country = 'canada'
两次。
更新:显示多个重复标记
select
o.vendor_id
,o.vndr_name_shrt_user
,O.COUNTRY
,O.VENDOR_NAME_SHORT
,B.POSTAL
,B.ADDRESS1
,OC.SAME_SHORT_NAME
,oc.SAME_USER_NUM
,'SAME_USER_NUM' as duplicateFlag
from VENDOR o
JOIN vendor_addr B ON o.VENDOR_ID = B.VENDOR_ID
WHERE O.COUNTRY ='CANADA'
AND B.COUNTY = 'CANADA'
AND o.vndr_name_shrt_user in
(
SELECT
vndr_name_shrt_user
FROM VENDOR
WHERE COUNTRY = o.country
AND VENDOR_STATUS = 'A'
GROUP BY vndr_name_shrt_user
HAVING COUNT(*) > 1
)
UNION ALL
select
o.vendor_id
,o.vndr_name_shrt_user
,O.COUNTRY
,O.VENDOR_NAME_SHORT
,B.POSTAL
,B.ADDRESS1
,OC.SAME_SHORT_NAME
,oc.SAME_USER_NUM
,'VENDOR_NAME_SHORT' as duplicateFlag
from VENDOR o
JOIN vendor_addr B ON o.VENDOR_ID = B.VENDOR_ID
WHERE O.COUNTRY ='CANADA'
AND B.COUNTY = 'CANADA'
AND o.VENDOR_NAME_SHORT in
(
SELECT
VENDOR_NAME_SHORT
FROM VENDOR
WHERE COUNTRY = o.country
AND VENDOR_STATUS = 'A'
GROUP BY VENDOR_NAME_SHORT
HAVING COUNT(*) > 1
)
答案 1 :(得分:0)
让我们有一些有趣的数据,在不同的属性上链接重复:
CREATE TABLE data ( ID, A, B, C ) AS
SELECT 1, 1, 1, 1 FROM DUAL UNION ALL -- Related to #2 on column A
SELECT 2, 1, 2, 2 FROM DUAL UNION ALL -- Related to #1 on column A, #3 on B & C, #5 on C
SELECT 3, 2, 2, 2 FROM DUAL UNION ALL -- Related to #2 on columns B & C, #5 on C
SELECT 4, 3, 3, 3 FROM DUAL UNION ALL -- Related to #5 on column A
SELECT 5, 3, 4, 2 FROM DUAL UNION ALL -- Related to #2 and #3 on column C, #4 on A
SELECT 6, 5, 5, 5 FROM DUAL; -- Unrelated
现在,我们可以使用分析函数(没有任何连接)获得一些关系:
SELECT d.*,
LEAST(
FIRST_VALUE( id ) OVER ( PARTITION BY a ORDER BY id ),
FIRST_VALUE( id ) OVER ( PARTITION BY b ORDER BY id ),
FIRST_VALUE( id ) OVER ( PARTITION BY c ORDER BY id )
) AS duplicate_of
FROM data d;
给出了:
ID A B C DUPLICATE_OF
-- - - - ------------
1 1 1 1 1
2 1 2 2 1
3 2 2 2 2
4 3 3 3 4
5 3 4 2 2
6 5 5 5 6
但是,并不认为#4与#5相关,而#5与#2相关,然后与#1相关......
这可以通过分层查询找到:
SELECT id, a, b, c,
CONNECT_BY_ROOT( id ) AS duplicate_of
FROM data
CONNECT BY NOCYCLE ( PRIOR a = a OR PRIOR b = b OR PRIOR c = c );
但是这会产生很多很多重复的行(因为它不知道从哪里开始层次结构,因此将依次选择每一行作为根) - 而是可以使用第一个查询来为层次结构查询提供一个开始当ID
和DUPLICATE_OF
值相同时指向
SELECT id, a, b, c,
CONNECT_BY_ROOT( id ) AS duplicate_of
FROM (
SELECT d.*,
LEAST(
FIRST_VALUE( id ) OVER ( PARTITION BY a ORDER BY id ),
FIRST_VALUE( id ) OVER ( PARTITION BY b ORDER BY id ),
FIRST_VALUE( id ) OVER ( PARTITION BY c ORDER BY id )
) AS duplicate_of
FROM data d
)
START WITH id = duplicate_of
CONNECT BY NOCYCLE ( PRIOR a = a OR PRIOR b = b OR PRIOR c = c );
给出了:
ID A B C DUPLICATE_OF
-- - - - ------------
1 1 1 1 1
2 1 2 2 1
3 2 2 2 1
4 3 3 3 1
5 3 4 2 1
1 1 1 1 4
2 1 2 2 4
3 2 2 2 4
4 3 3 3 4
5 3 4 2 4
6 5 5 5 6
由于搜索中出现#4的局部最小值,仍有一些行是重复的,可以使用简单的GROUP BY
删除:
SELECT id, a, b, c,
MIN( duplicate_of ) AS duplicate_of
FROM (
SELECT id, a, b, c,
CONNECT_BY_ROOT( id ) AS duplicate_of
FROM (
SELECT d.*,
LEAST(
FIRST_VALUE( id ) OVER ( PARTITION BY a ORDER BY id ),
FIRST_VALUE( id ) OVER ( PARTITION BY b ORDER BY id ),
FIRST_VALUE( id ) OVER ( PARTITION BY c ORDER BY id )
) AS duplicate_of
FROM data d
)
START WITH id = duplicate_of
CONNECT BY NOCYCLE ( PRIOR a = a OR PRIOR b = b OR PRIOR c = c )
)
GROUP BY id, a, b, c;
给出了输出:
ID A B C DUPLICATE_OF
-- - - - ------------
1 1 1 1 1
2 1 2 2 1
3 2 2 2 1
4 3 3 3 1
5 3 4 2 1
6 5 5 5 6