SQL连接两个表,但如果第二个表中存在第一个表,则覆盖第一个表

时间:2018-11-05 20:56:06

标签: mysql sql join

我无法使此查询按我希望的方式工作。我有两个具有几乎相同数据的表,但希望其中一个可以覆盖另一个(如果存在)。一个例子比尝试解释要容易:

有未调整的余额表:

unadjusted_balance

以及用于每个余额调整的单独表格 enter image description here

所需的输出具有未调整的余额,并在其之上进行任何现有的调整(如果is_current = 1)...本质上替代了该行,但仍保持原始的未调整的current_balance。

所需的输出将是这样的:

enter image description here

这是我当前无法使用的查询...它正在翻转值并缺少current_balance。我已经尝试了好几个小时,却无法到达任何地方:

SELECT
*
FROM
  (
    SELECT
      balance_adjustments.name,
      balance_adjustments.user_id,
      balance_adjustments.amount_owed,
      balance_adjustments.when_to_pay,
      balance_adjustments.current_balance
    FROM
      balance_adjustments
    WHERE
      balance_adjustments.when_to_pay = '2018-11-05'
      AND balance_adjustments.is_current = true
    UNION ALL
    SELECT
      unadjusted_balance.name,
      unadjusted_balance.user_id,
      unadjusted_balance.amount_owed,
      unadjusted_balance.when_to_pay,
      unadjusted_balance.current_balance
    FROM
      unadjusted_balance
      LEFT OUTER JOIN balance_adjustments ON balance_adjustments.user_id = unadjusted_balance.user_id
      AND balance_adjustments.name = unadjusted_balance.name
      AND balance_adjustments.when_to_pay = unadjusted_balance.when_to_pay
      AND balance_adjustments.is_current = true
    WHERE
      unadjusted_balance.when_to_pay = '2018-11-05'
      AND balance_adjustments.name IS NULL
  ) AS table1

一些其他命令可以帮助任何人设置此场景进行测试:

CREATE TABLE balance_adjustments
(
name varchar(30),
    user_id varchar(30),
    amount_owed float,
    when_to_pay datetime,
    current_balance float,
    is_current boolean
);


CREATE TABLE unadjusted_balance
(
name varchar(30),
    user_id varchar(30),
    amount_owed float,
when_to_pay datetime,
current_balance float
);


insert into balance_adjustments values ('ricardo', '82340001', 100.00, '2018-11-05', null, 1)
insert into balance_adjustments values ('ricardo', '82340001', 33.00, '2018-11-05', null, 0)

insert into unadjusted_balance values ('joseph', '82340000', 2400.00, '2018-11-05', 4049.00)
insert into unadjusted_balance values ('ricardo', '82340001', 899.00, '2018-11-05', 500.00)

感谢您的帮助

2 个答案:

答案 0 :(得分:1)

如果您想用余额调整来覆盖未调整的余额,请执行以下操作:

  • 选择所有未调整的余额。
  • 直接加入调整项,以便获得任何调整项,确保滤除is_current = 1的那些人。
  • 使用调整中的欠款总额求出覆盖金额。
  • 要在没有调整的情况下默认为原始值,请在总和之外使用合并,并将原始量用作第二个参数。

如果不为空,Coalesce将返回第一个值,否则返回下一个参数的值。如果左联接未返回任何行,则总和的结果将为null。

查询

SELECT ub.name
    , ub.user_id
    , COALESCE(SUM(ba.amount_owed), ub.amount_owed) AS amount_owed 
    , ub.when_to_pay
    , ub.current_balance
FROM @unadjusted_balance AS ub
LEFT JOIN @balance_adjustments AS ba ON ba.user_id = ub.user_id AND ba.is_current = 1
GROUP BY ub.name, ub.user_id, ub.amount_owed, ub.when_to_pay, ub.current_balance;

我不确定is_current等于1的情况下是否可以进行多个调整。如果最多只有一行,则忽略合计和分组并仅传递ba .amount_owed作为合并中的第一个参数。

答案 1 :(得分:1)

如果您只想用amount_owed表中balance_adjustments为1的值替换is_current(我假设这些值只有一个),则简单的LEFT JOINCOALESCE就足够了。 COALESCE确保NULL表中不匹配行中的任何balance_adjustments值都被unadjusted_balances表中的原始值替换。从您的问题尚不清楚,您是否也想替换when_to_pay字段,我假设您在此查询中也有。否则,只需将COALESCE(ba.when_to_pay, ub.when_to_pay) AS when_to_pay替换为ub.when_to_pay

SELECT ub.name, ub.user_id, 
    COALESCE(ba.amount_owed, ub.amount_owed) AS amount_owed,
    COALESCE(ba.when_to_pay, ub.when_to_pay) AS when_to_pay,
    ub.current_balance
FROM unadjusted_balance ub
LEFT JOIN balance_adjustments ba ON ba.user_id = ub.user_id AND ba.is_current
ORDER BY ub.name

输出:

name        user_id     amount_owed     when_to_pay             current_balance
joseph      82340000    2400            2018-11-05 00:00:00     4049
ricardo     82340001    100             2018-11-05 00:00:00     500

Demo on dbfiddle