Nig*_*loo 2 subquery sybase-sql-anywhere
我有这样的查询
SELECT *
FROM my_table
WHERE ... AND id IN (SELECT t2.id
FROM my_table t2
WHERE id = t2.id AND ... );
Run Code Online (Sandbox Code Playgroud)
我知道在这个例子中我可以组合这两个WHERE
子句并且不使用子查询,但这不是重点。
此查询在我使用的 DBMS(SQL Anywhere 16)上完美运行,但我想知道id
在子查询中my_table.id
从主查询引用的事实是否是标准行为,或者我是否只是幸运。
链接或参考 RFC 或任何官方文件表示赞赏:)
不,这是错误的。标准行为是在WHERE id = ...
子查询中id
引用范围内最近的表。那就是t2
。my_table
仅当t2
没有id
列时,它才会在外部查询中引用。
不过你很幸运,因为WHERE id = t2.id
- 被翻译为WHERE t2.id = t2.id
实际上并不需要,因为你使用了WHERE id IN (subquery)
. 如果你有一个EXISTS
版本,它不会像你预期的那样工作。
因此,编写查询的正确方法要么是所有列引用的前缀:
SELECT t1.*
FROM my_table AS t1
WHERE ... AND t1.id IN
(SELECT t2.id
FROM my_table t2
WHERE --- t1.id = t2.id AND -- remove, we don't need this
... );
Run Code Online (Sandbox Code Playgroud)
或者只在需要时非常小心和前缀:
SELECT *
FROM my_table AS t1
WHERE ... AND id IN
(SELECT id
FROM my_table t2
WHERE --- id = t2.id AND -- remove, we still don't need this
... );
Run Code Online (Sandbox Code Playgroud)
我仍然更喜欢EXISTS
此类查询的版本:
SELECT t1.*
FROM my_table AS t1
WHERE ... AND EXISTS
(SELECT *
FROM my_table t2
WHERE t1.id = t2.id AND -- we do need "t1". here
... );
Run Code Online (Sandbox Code Playgroud)
或者(如果你总是很小心的话):
SELECT *
FROM my_table AS t1
WHERE ... AND EXISTS
(SELECT *
FROM my_table t2
WHERE t1.id = id AND -- we need only the "t1". here
-- the second ref, = id is translated
-- to: = t2.id
... );
Run Code Online (Sandbox Code Playgroud)