我有一个主表(PO_BreakOutAll
),其中有大约3000行,只有两列(PO_ID
,PO_LN_NO
)组成了主键。我还有几个其他的表,每个表都有一个来自主表的数据子集(或者它应该是这样)。所有表都与主表相同。
所有表都有这个确切的架构:
PO_ID char(5) PK
PO_LN_NO int PK
我需要进行两种不同类型的比较以进行验证并查找重复项。
首先确保主表中的每一行都存在于其他子表中的一个且仅存在一个子表中。
其次,我需要确保在任何子表中都没有重复行。同一行可以存在于两个或多个子表中,我需要找到它们。
我可以在单独的查询中执行每个表,但还没有弄清楚如何编写一个查询来同时比较所有子表。
这是我到目前为止所做的,但它不起作用:
SELECT a.PO_ID as all_PO,
a.PO_LN_NO,
c.PO_ID as Cummings_PO,
c.PO_LN_NO,
f.PO_ID as filter_PO,
f.PO_LN_NO,
fo.PO_ID as fixedObl_PO,
fo.PO_LN_NO
FROM
PO_BreakOutAll a
LEFT OUTER JOIN
PO_Cummins c ON (c.PO_ID = a.PO_ID AND c.PO_LN_NO = a.PO_LN_NO)
LEFT OUTER JOIN
PO_Filters f ON (f.PO_ID = a.PO_ID AND f.PO_LN_NO = a.PO_LN_NO)
LEFT OUTER JOIN
PO_FixedOblig fo ON (fo.PO_ID = a.PO_ID AND fo.PO_LN_NO = a.PO_LN_NO)
答案 0 :(得分:1)
我不会将join
用于此;我会用union all
。这是一种计算记录如何在表间重叠的方法:
select isAll, isCummins, isFilters, isOblig, count(*)
from (select PO_ID, PO_LN_NO, sum(isAll) as isAll, sum(isCummins) as isCummins,
sum(isFilters) as isFilters, sum(isOblig) as isOblig
from ((select PO_ID, PO_LN_NO, 1 as isAll, 0 as isCummins, 0 as isFilters, 1 as isOblig
from PO_BreakOutAll
) union all
(select PO_ID, PO_LN_NO, 0, 1, 0, 0
from PO_Cummins
) union all
(select PO_ID, PO_LN_NO, 0, 0, 1, 0
from PO_Filters
) union all
(select PO_ID, PO_LN_NO, 0, 0, 0, 1
from PO_FixedOblig
)
) t
group by PO_ID, PO_LN_NO
) t
group by isAll, isCummins, isFilters, isOblig;
如果要查找未通过测试的行,只需使用带有where
条件的子查询:
select PO_ID, PO_LN_NO, sum(isAll) as isAll, sum(isCummins) as isCummins,
sum(isFilters) as isFilters, sum(isOblig) as isOblig
from ((select PO_ID, PO_LN_NO, 1 as isAll, 0 as isCummins, 0 as isFilters, 1 as isOblig
from PO_BreakOutAll
) union all
(select PO_ID, PO_LN_NO, 0, 1, 0, 0
from PO_Cummins
) union all
(select PO_ID, PO_LN_NO, 0, 0, 1, 0
from PO_Filters
) union all
(select PO_ID, PO_LN_NO, 0, 0, 0, 1
from PO_FixedOblig
)
) t
group by PO_ID, PO_LN_NO
having sum(isAll) <> 1 or
(sum(isAll) = 1 and (sum(isCummins) + sum(isFilters) + sum(isOblig) <> 1)
);
答案 1 :(得分:1)
我认为@gordon linoff有一个整体解决方案。如果您想使用CTE范例,可以使用example based on your Fiddle来回答重复的问题:
WITH CTE (PO_ID,PO_LN_NO,TableName) AS
(SELECT
PO_ID,
PO_LN_NO,
'Cummings' as TableName
FROM PO_Cummins
UNION ALL
SELECT
PO_ID,
PO_LN_NO,
'Filters' as TableName
FROM PO_Filters
UNION ALL
SELECT
PO_ID,
PO_LN_NO,
'Office' as TableName
FROM PO_Office )
SELECT
PO_BreakOutAll.PO_ID,
PO_BreakOutAll.PO_LN_NO,
CHILD_DATA.TABLENAME AS DUP_TABLENAME
FROM
PO_BreakOutAll
INNER JOIN (
SELECT PO_ID, PO_LN_NO, COUNT(1) AS DUP_COUNTER
FROM CTE
GROUP BY PO_ID, PO_LN_NO
HAVING COUNT(1) > 1
) DUPS ON DUPS.PO_ID = PO_BreakOutAll.PO_ID AND DUPS.PO_LN_NO = PO_BreakOutAll.PO_LN_NO
INNER JOIN (
SELECT PO_ID, PO_LN_NO, TABLENAME
FROM CTE
) CHILD_DATA
ON CHILD_DATA.PO_ID = PO_BreakOutAll.PO_ID AND CHILD_DATA.PO_LN_NO = PO_BreakOutAll.PO_LN_NO
ORDER BY PO_ID, PO_LN_NO, DUP_TABLENAME