如果列的值存在于另一个 table 中,则过滤连接的行

Filter joined rows if column's value exists in another table

今天遇到如下问题(fiddle here):

create table ta02 
(
  t_key      varchar(255) default null,
  ta_over_amount decimal(13,2) default null,
  name           varchar(255) default null
);

和:

create table voucher 
(
  v_key       varchar(255) default null,
  over_amount decimal(13,2) default null,
  signature   varchar(255) default null
);

填充:

INSERT INTO ta02 (t_key, ta_over_amount, name) VALUES ('gogo', 100.00, 'anh');
INSERT INTO ta02 (t_key, ta_over_amount, name) VALUES ('gogo', 50.00, 'duc');
INSERT INTO ta02 (t_key, ta_over_amount, name) VALUES ('logbasex', 25.00, 'ho');
INSERT INTO ta02 (t_key, ta_over_amount, name) VALUES ('logbasex', 15.00, 'phi');

和:

INSERT INTO voucher (v_key, over_amount, signature) VALUES ('gogo', 100.00, 'blue');
INSERT INTO voucher (v_key, over_amount, signature) VALUES ('gogo', 50.00, 'white');
INSERT INTO voucher (v_key, over_amount, signature) VALUES ('logbasex', 14.00, 'itsme');
INSERT INTO voucher (v_key, over_amount, signature) VALUES ('logbasex', 25.00, 'green');

这是我的没有任何条件的连接查询:

select t.name, t.ta_over_amount, v.over_amount, v.signature 
from ta02 t 
left join voucher v on t.t_key = v.v_key;

结果:

name    ta_over_amount  over_amount     signature
anh     100.00           50.00          white
anh     100.00          100.00          blue
duc     50.00            50.00          white
duc     50.00           100.00          blue
ho      25.00            25.00          green
ho      25.00            15.00          itsme
phi     15.00            25.00          green
phi     15.00            15.00          itsme

需要的条件是:

这是我想要的结果:

    +----+--------------+-----------+---------+
    |name|ta_over_amount|over_amount|signature|
    +----+--------------+-----------+---------+
    |phi |15.00         |14.00      |itsme    |
    +----+--------------+-----------+---------+
ta02 table                                
+--------+--------------+----+
|key     |ta_over_amount|name|
+--------+--------------+----+
|gogo    |100.00        |anh |
|gogo    |50.00         |duc |
|logbasex|25.00         |ho  |
|logbasex|15.00         |phi |
+--------+--------------+----+

voucher table
+--------+-----------+---------+
|key     |over_amount|signature|
+--------+-----------+---------+
|gogo    |110.00     |blue     |
|gogo    |50.00      |white    |
|logbasex|25.00      |itsme    |
|logbasex|15.00      |green    |
+--------+-----------+---------+

My expected result is:
+----+--------------+-----------+---------+
|name|ta_over_amount|over_amount|signature|
+----+--------------+-----------+---------+
|anh |100.00        |110.00     |blue     |
+----+--------------+-----------+---------+

- 100 doesn't match 110, I include this one in the desired result.
- 100 doesn't match 50, but 50 exits in ta_over_amount list, ignore
- 50  doesn't match 110, but 50 exits in over_amount list, ignore
- 50 match 50, ignore

这个样本真的代表了你的完整table吗? table 确实需要一个唯一的键,这将使您的查询变得更加容易。

因为获得所需结果的一种可能方法是 not existsnot in 使用 cte 以便于参考。

I've amended your fiddle with a new query that gives your desired output

with t as (
    select *, case when exists (
                select * from voucher v 
                where v.v_key=t.t_key and v.over_amount=t.ta_over_amount)
              then 1 else 0 end excl
    from ta02 t
)
select t.name, t.ta_over_amount, v.over_amount, v.signature
from t join voucher v on v.v_key=t.t_key 
where t.excl=0 and v.over_amount not in (select ta_over_amount from t where excl=1)

编辑

所以球门柱跳了一点以排除 MySql 8 而只支持 5.7,这意味着 CTE 不能使用

select t.name, t.ta_over_amount, v.over_amount, v.signature
from ta02 t join voucher v on v.v_key=t.t_key 
where not exists (select * from voucher v where v.v_key=t.t_key and v.over_amount=t.ta_over_amount)
    and v.over_amount 
    not in (select ta_over_amount from ta02 t2 where t2.t_key=v.v_key and v.over_amount=t2.ta_over_amount)

Revised Fiddle