如果列的值存在于另一个 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
需要的条件是:
在同一个v_key
上,只连接ta_over_amount
值不等于匹配行对应over_amount
值的行和列表ta_over_amount
值(通过ta02
中的joined key v_key
得到table)不包含over_amount
值,列表over_amount
值(通过joined得到voucher
table 中的键 v_key
) 不包含 ta_over_amount
值。
例如,当在 ta02
table 中连接两个 table 时 v_key
= gogo
(第一行),这将匹配 voucher
table 中的两个对应行,其中包括 signature
= blue 和 white分别。一行有 signature
= blue,over_amount
值 = 100 等于 ta_over_amount
值然后我忽略该行(显然不t 满足我的条件),一行有 signature
= white,over_amount
值 = 50 不等于 ta_over_amount
但存在于列表中ta_over_amount
值 v_key
= gogo
在 ta02
table 那么我也需要忽略这一行。
这是我想要的结果:
+----+--------------+-----------+---------+
|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 exists
和 not 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)
今天遇到如下问题(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
需要的条件是:
在同一个
v_key
上,只连接ta_over_amount
值不等于匹配行对应over_amount
值的行和列表ta_over_amount
值(通过ta02
中的joined keyv_key
得到table)不包含over_amount
值,列表over_amount
值(通过joined得到voucher
table 中的键v_key
) 不包含ta_over_amount
值。例如,当在
ta02
table 中连接两个 table 时v_key
=gogo
(第一行),这将匹配voucher
table 中的两个对应行,其中包括signature
= blue 和 white分别。一行有signature
= blue,over_amount
值 = 100 等于ta_over_amount
值然后我忽略该行(显然不t 满足我的条件),一行有signature
= white,over_amount
值 = 50 不等于ta_over_amount
但存在于列表中ta_over_amount
值v_key
=gogo
在ta02
table 那么我也需要忽略这一行。
这是我想要的结果:
+----+--------------+-----------+---------+
|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 exists
和 not 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)