我有两张桌子:
ID, ACC, AE_CCY, DRCR_IND, AMOUNT, MODULE
ID, ACC, AE_CCY, DRCR_IND, AMOUNT, MODULE
我想显示的差异仅通过:AE_CCY, DRCR_IND, AMOUNT, MODULE
和ACC
按前4个字符进行比较
示例:
ID ACC AE_CCY DRCR_IND AMOUNT MODULE
-- --------- ------ -------- ------ ------
1 734647674 USD D 100 OP
并在flex中:
ID ACC AE_CCY DRCR_IND AMOUNT MODULE
-- --------- ------ -------- ------ ------
1 734647654 USD D 100 OP
2 734665474 USD D 100 OP
9 734611111 USD D 100 OP
ID 2和9应显示为差异。
如果我使用 FULL JOIN ,我会得到没有差异,因为substr(account.ACC,1,4) = substr(flex.ACC,1,4)
是相等的而其他人是相等的,而MINUS不起作用,因为ID不同。
答案 0 :(得分:1)
你的意思是你想按ACC的前4个字符分组,然后区分它们吗?
而且,如果没有,为什么Flex:ID = 1与帐户不同:ID = 1,如果ID = 2且ID = 9,特别是因为它读取ID不是比较字段?
答案 1 :(得分:0)
蛮力集理论答案:
SELECT * FROM ID
UNION
SELECT * FROM FLEX
MINUS
(SELECT * FROM ID
INTERSECT
SELECT * FROM FLEX)
答案 2 :(得分:0)
我认为您想要的是具有附加条件的完整联接。类似的东西:
select F.ID, F.AE_CCY, F.DRCR_IND, F.AMOUNT, F.MODULE, F.ACC
from account a join flex f
on substr(a.ACC,1,4) = substr(f.ACC,1,4)
where a.AE_CCY <> f.AE_CCY
or a.DRCR_IND <> f.DRCR_IND
or a.AMOUNT <> f.AMOUNT
or a.MODULE <> f.MODULE
or a.ACC <> f.ACC
这样,仍然会对前4个字符执行连接,但where条件会检查整个字段(以及其他四个字符)。
修改后的解决方案:这是一个黑暗中的东西,我想知道你真正想要的是一个没有记录的记录列表在另一张表中匹配。在这种情况下,完整的外部联接可能就是答案:
select coalesce(F.ID,a.ID) as ID,
coalesce(F.AE_CCY,a.AE_CCY) as AE_CCY,
coalesce(F.DRCR_IND,a.DRCR_IND) as DRCR_IND,
coalesce(F.AMOUNT,a.AMOUNT) as AMOUNT,
coalesce(F.MODULE,a.MODULE) as MODULE,
coalesce(F.ACC,a.ACC) as ACC
from account a full outer join flex f
on substr(a.ACC,1,4) = substr(f.ACC,1,4)
and a.AE_CCY = f.AE_CCY
and a.DRCR_IND = f.DRCR_IND
and a.AMOUNT = f.AMOUNT
and a.MODULE = f.MODULE
where a.id is null
or f.id is null
第三次尝试解决方案:进一步思考,我想你是说你希望第一个表中的每个记录与第二个表中的一个记录匹配(反之亦然) 。这是一个难题,因为关系数据库并不是真正的设计工作。
下面的解决方案再次使用完全外部联接,以仅获取未出现在另一个表中的行。这次,我们添加ROW_NUMBER为每个表中的一组重复值的每个成员分配一个唯一的编号。在您的注释示例中,一个表中有5个相同的行,另一个表中有1个相同的行,第一个表将编号为1-5,第二个表将为1.因此,通过将其添加为连接条件,我们确保每一行只有一个匹配。这种设计的一个缺陷是ACC上的完美匹配不能保证优先于另一个值。做这项工作会有点困难。
select coalesce(F.ID,a.ID) as ID,
coalesce(F.AE_CCY,a.AE_CCY) as AE_CCY,
coalesce(F.DRCR_IND,a.DRCR_IND) as DRCR_IND,
coalesce(F.AMOUNT,a.AMOUNT) as AMOUNT,
coalesce(F.MODULE,a.MODULE) as MODULE,
coalesce(F.ACC,a.ACC) as ACC
from (select a.*,
row_number()
over (partition by AE_CCY,DRCR_IND,AMOUNT,MODULE,substr(ACC,1,4)
order by acc) as rn
from account a) a
full outer join
(select f.*,
row_number()
over (partition by AE_CCY,DRCR_IND,AMOUNT,MODULE,substr(ACC,1,4)
order by acc) as rn
from flex f) f
on substr(a.ACC,1,4) = substr(f.ACC,1,4)
and a.AE_CCY = f.AE_CCY
and a.DRCR_IND = f.DRCR_IND
and a.AMOUNT = f.AMOUNT
and a.MODULE = f.MODULE
and a.RN = f.RN
where a.id is null
or f.id is null
答案 3 :(得分:0)
我喜欢使用:
SELECT min(which) which, id, ae_ccy, drcr_ind, amount, module, acc
FROM (SELECT DISTINCT 'account' which, id, ae_ccy, drcr_ind, amount, module,
substr(acc, 1, 4) acc
FROM ACCOUNT
UNION ALL
SELECT DISTINCT 'flex' which, id, ae_ccy, drcr_ind, amount, module,
substr(acc, 1, 4) acc
FROM flex)
GROUP BY id, ae_ccy, drcr_ind, amount, module, acc
HAVING COUNT(*) != 2
ORDER BY id, 1
它将显示新行,旧的缺失行和任何差异。