从两个表中查询数据,只选择修改过的记录

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”只是一种查询语言,而不是特定数据库产品的名称。请为您正在使用的数据库产品添加tag postgresql, oracle, sql-server, db2, ... 【参考方案1】:

我认为获得所需内容的最简单方法是使用left joinunion 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;

【讨论】:

以上是关于从两个表中查询数据,只选择修改过的记录的主要内容,如果未能解决你的问题,请参考以下文章

通过只知道没有时间的日期从表中选择 (ORACLE)

从表中选择最后修改的数据记录

ComboBox 只选择第一条记录

从表中检索所有不同的记录,如果两个相似的不同记录之间发生任何更改,则需要同时考虑两者。使用选择查询

如何从访问表中获取选择性记录

当查询返回多个 min(count) 数据时,如何从不同表中选择所有行