从两个表中查询数据,只选择修改过的记录
Posted
技术标签:
【中文标题】从两个表中查询数据,只选择修改过的记录【英文标题】:Query data from two tables and select only modified records 【发布时间】:2018-06-06 10:14:53 【问题描述】:我想做的是:
我有一个 TableA 包含所有记录。
account | name | items | amount
0017532 A 3 1500
0034524 B 5 700
7772618 C 7 300
5467382 D 2 450
7772618 C 6 2200
另一个 TableB 包含:
account | name | items | amount
0034524 B 2 200
5467382 D 1 50
6483232 E 1 25
想要的查询结果是:
account | name | items | amount
0017532 A 3 1500
0034524 B 3 500
7772618 C 7 300
5467382 D 1 400
6483232 E 1 25
7772618 C 6 2200
如果TableB中有记录那么 TableA.item - TableB.item 和 TableB.amount - TableB.amount
结果应包含表A中的所有记录以及上述减法的结果。
我加入TableA和TableB并执行减法运算,但结果仅返回与TableB中记录数匹配的记录
account | name | items | amount
0034524 B 3 500
5467382 D 1 400
6483232 E 1 25
当我尝试使用查询 TableA 进行上述 UNION 减法查询时,结果发现两个表的记录都列出了:
account | name | items | amount
0017532 A 3 1500
0034524 B 5 700
0034524 B 3 500
7772618 C 7 300
5467382 D 2 450
5467382 D 1 400
7772618 C 6 2200
6483232 E 1 25
如果 TableA 中存在“帐户”和“名称”,我正在尝试找到一种仅从 TableB 中选择记录的方法。
【问题讨论】:
你能把你写的查询也贴出来吗? 您使用的是哪个DBMS product? “SQL”只是一种查询语言,而不是特定数据库产品的名称。请为您正在使用的数据库产品添加tagpostgresql
, oracle
, sql-server
, db2
, ...
【参考方案1】:
我认为获得所需内容的最简单方法是使用left join
和union all
:
select a.account, a.name,
(a.items - coalesce(b.items, 0)) as items,
(a.amount - coalesce(b.amount, 0)) as amount
from a left join
b
on a.account = b.account
union all
select b.account, b.name, b.items, b.amount
from b
where not exists (select 1
from a
where a.account = b.account
);
你也可以使用full join
,但是逻辑很麻烦,因为b
的数据上有符号:
select coalesce(a.account, b.account) as account,
coalesce(a.name, b.name) as name,
(case when a.account is null then b.items
else a.items - coalesce(b.items, 0)
end) as items,
(case when a.account is null then b.amount
else a.amount - coalesce(b.amount, 0)
end) as items
from a full join
b
on a.account = b.account;
【讨论】:
【参考方案2】:如果每个表中的帐户不是唯一的? 那么你可能只想用 B 减去 A 一次。
在这种情况下,您还可以根据帐户和计算的 row_number 完全加入它们。
假设您的数据库支持诸如 row_number 之类的窗口函数顺便说一句,i.m.h.o。这些预期结果对我来说似乎具有误导性
样本数据
create table TableA (account char(7), name char(1), items integer, amount integer);
create table TableB (account char(7), name char(1), items integer, amount integer);
insert into TableA (account, name, items, amount) values
('1111111', 'A', 10, 100),
('2222222', 'B', 20, 200),
('3333333', 'C', 30, 310),
('3333333', 'C', 30, 320),
('4444444', 'D', 40, 400),
('6666666', 'F', 60, 610),
('6666666', 'F', 60, 620);
insert into TableB (account, name, items, amount) values
('2222222', 'B', 10, 100),
('4444444', 'D', 10, 100),
('5555555', 'E', 10, 100),
('6666666', 'F', 10, 100);
查询:
select
coalesce(a.account, b.account) as Account,
coalesce(a.name, b.name) as Name,
coalesce(case when a.items is not null and b.items is not null then a.items - b.items end, a.items, b.items) as Items,
coalesce(case when a.amount is not null and b.amount is not null then a.amount - b.amount end, a.amount, b.amount) as Amount
from
(
select account, name, items, amount,
row_number() over (partition by account order by amount) as rn
from TableA
) as a
full join
(
select account, name, items, amount,
row_number() over (partition by account order by amount) as rn
from TableB
) as b on (B.account = A.account and B.rn = A.rn)
order by Account;
【讨论】:
以上是关于从两个表中查询数据,只选择修改过的记录的主要内容,如果未能解决你的问题,请参考以下文章