话说这两个 sql 为啥和我预想的不太一样

2020-11-03 10:36:20 +08:00
 luxinfl
select * from t1  where  not exists (select 1 from t2 where t1.name = t2.name)

select * from t1  where exists (select 1 from t2 where t1.name != t2.name)

我本意是找 t1 比 t2 多的数据,结果把 t1 的所有东西都返回了

3004 次点击
所在节点    程序员
24 条回复
BrettD
2020-11-03 10:47:09 +08:00
为啥要这样写
luxinfl
2020-11-03 10:47:35 +08:00
@BrettD 因为不存在嘛。。。
luxinfl
2020-11-03 10:50:03 +08:00
话说换成 in,比较容易看出来一下吧,应该是等价于
```
select * from t1 where not in(select name from t2)
第二个好像不太对
```
wisunny
2020-11-03 10:50:47 +08:00
翻译成汉语就好理解多了,一个是不存在相等的,一个是存在不等的。而存在不等的只要存在一个就始终为 true,结果自然不一样
chendy
2020-11-03 10:51:49 +08:00
select 1 from t2 where t1.name != t2.name 这个…只要有不同的就有返回,于是就返回全部呗
luxinfl
2020-11-03 11:06:57 +08:00
@wisunny 那这个怎么遍历的啊,感觉怪怪的
luxinfl
2020-11-03 11:08:19 +08:00
@chendy 所以说第二个 sql 就相当于直接 select * from t1 ?
chendy
2020-11-03 11:11:20 +08:00
@luxinfl 也不是但是差不多,只要 t2 有数据,而且不全都和 t1 的 name 一样就有返回
kiracyan
2020-11-03 11:12:04 +08:00
select * from t1 where name not in (select name from t2)
no1xsyzy
2020-11-03 11:21:31 +08:00
@luxinfl 除非 t2 里只有一条
把 SQL 重新写为集合推导式:

式 1 等价于
\{ x | x \in t1, \neg \exists_{y \in t2} (x.name = y.name) \}
= \{ x | x \in t1, \forall_{y \in t2} (x.name \neq y.name) \}

式 2 等价于
\{ x | x \in t1, \exists_{y \in t2} (x.name \neq y.name) \}

你觉得一样吗?
luxinfl
2020-11-03 11:23:45 +08:00
@chendy 但是我 t1 和 t2 的表数据一样,第二个 sql 还是有返回啊
YYYYMMDDHHSS
2020-11-03 11:25:46 +08:00
翻译:1,对于 T1 的某一行,只要存在一行 T2.NAME == T1.NAME,就返回 T1.*;
2,对于 T1 的某一行,只要存在一行 T2.NAME <> T1.NAME.就返回 T1.*; 那么哪怕真的只有一个 name 不在 T1 中,对于任何一个 T1 行都满足....
no1xsyzy
2020-11-03 11:27:39 +08:00
话说
select * from t1 where name not in (select name from t2)

select t1.* from t1 left join t2 on t1.name = t2.name where t2.name = null
两个相比效率如何?

但第二个可读性太差了,又要 t1.name = t2.name 又要 t2.name = null…… 还是我的(奇技淫巧)写法有问题?
如果效率只稍高一点还是不要用 2,如果效率提升非常高那就加注释
no1xsyzy
2020-11-03 11:29:29 +08:00
@luxinfl 注意 “不全都和”
这个 name 被认为 TLD 太傻了……
顺便试试:
`t1`.name [t1].name
wolfie
2020-11-03 11:30:00 +08:00
t2 如果是空表,exists 直接返回 false 。
第二条 sql 跟你需求不一样。
luxinfl
2020-11-03 11:34:05 +08:00
@no1xsyzy 第一个是不是相当于
for x in t1:
for y in t2:
if(x.name == y.name):
result.add(x)
break;
luxinfl
2020-11-03 11:34:46 +08:00
@luxinfl 不对,条件写错了。。。
no1xsyzy
2020-11-03 12:53:18 +08:00
@luxinfl 啊,用 Python 解释的话这么写吧:
式 1:
[x for x in t1 if not any(x['name'] == y['name'] for y in t2)]
根据反演律展开,其等价于
[x for x in t1 if all(x['name'] != y['name'] for y in t2)]

式 2:
[x for x in t1 if any(x['name'] != y['name'] for y in t2)]

一个是 all 一个是 any
luxinfl
2020-11-03 13:47:00 +08:00
@no1xsyzy 谢谢大佬,这么看我就懂了。。
samv2
2020-11-03 13:51:35 +08:00
找 t1 比 t2 多的,可以这样写
select t1.* from t1
left join t2
on t1.name=t2.name
where t2.name is null

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/721270

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX