我有一些 SQL 可以告诉我从未使用过剑的 super 英雄。
创建表
首先,这是用于创建和填充表的 (MySQL) 脚本。
CREATE TABLE IF NOT EXISTS `mydb`.`weaponry` (
`hero` VARCHAR(20) NULL,
`weapon` VARCHAR(20) NULL)
ENGINE = InnoDB
insert into weaponry (hero, weapon) values ('Wonder Woman', 'Lasso of truth');
insert into weaponry (hero, weapon) values ('Wonder Woman', 'Sword');
insert into weaponry (hero, weapon) values ('Wonder Woman', 'Shield');
insert into weaponry (hero, weapon) values ('Spider Man', 'Web');
insert into weaponry (hero, weapon) values ('Gamora', 'Sword');
insert into weaponry (hero, weapon) values ('Gamora', 'Daggar');
insert into weaponry (hero, weapon) values ('Batman', 'Batarang');
insert into weaponry (hero, weapon) values ('Batman', 'Batgrapple');
insert into weaponry (hero, weapon) values ('Batman', 'Tranquilizer gun');
使用 NOT IN
的工作代码和一个子选择
select distinct hero from weaponry
where hero not in
(select hero from weaponry where weapon = 'Sword')
这正确地返回了没有使用剑的蜘蛛侠和 bat 侠。
备选方案 1:使用 NOT EXISTS
我想使用 NOT EXISTS
实现相同的查询.
我看了https://stackoverflow.com/a/5231731/509840 .
我试过这个:
select distinct hero from weaponry
where not exists
(select * from weaponry where weapon = 'Sword')
不幸的是,这不会返回任何行。
备选方案 2:使用 LEFT JOIN
我也看了这个答案:https://stackoverflow.com/a/17413996/509840 .
我很想尝试更换 NOT IN
用LEFT JOIN
.
select * from weaponry a
left join weaponry b on a.hero=b.hero and a.weapon=b.weapon
where a.weapon <> 'Sword'
但这只会返回所有非剑类英雄(包括神奇女侠和卡魔拉),因为所有英雄都使用剑以外的武器。
你能帮我用 NOT EXISTS
重写 NOT IN 查询吗?或 LEFT JOIN
?
编辑:Left Join 和相关子查询
@JeffUK 在他的评论中建议,通过删除 WHERE
可以更好地理解相关子查询。条款。这是对 select
的一个小修改。与 where
已删除。
select distinct a.hero, weaponryInner.hero from weaponry a
left join
(Select * from weaponry b where weapon = 'Sword') as weaponryInner
on a.hero=weaponryInner.hero
结果是两列英雄,其中一些是NULL
.
-------------------------------
Hero | Hero
-------------------------------
Wonder Woman | Wonder Woman
Gamora | Gamora
Spider Man | <null>
Batman | <null>
-------------------------------
所以添加最后的where weaponryInner.Weapon is null
只会返回蜘蛛侠和 bat 侠。
最佳答案
第一个检查是否存在任何持剑英雄,您只需要检查“当前”持剑英雄。
select distinct hero from weaponry as a
where not exists
(select * from weaponry as b where b.weapon = 'Sword' and b.hero = a.hero )
第二个对您不起作用,联接独立地作用于每一行,因此将完全按照您所看到的进行。你可以做这样的事情,有点复杂但可以完成工作。
我们在子查询中只找到带剑的英雄,并将其加入所有英雄,在子查询中找不到任何带有“NULL”的英雄,因此永远不要挥舞剑。
select distinct a.hero from weaponry a
left join
(Select * from weaponry b where weapon = 'Sword') as weaponryInner
on a.hero=weaponryInner.hero
where weaponryInner.Weapon is null
关于mysql - 转换一个有效的 SQL NOT IN,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44443887/