SQL左连接奇怪的语法错误?
==问题=== 我在3个表上使用了一个左连接SQL表达式。尝试运行MS ACCESS 2007时,我从中收到一个意外错误“不支持联接表达式” ==详细信息=== 这些桌子都是连在一起的SQL左连接奇怪的语法错误?,sql,syntax,join,ms-access-2007,Sql,Syntax,Join,Ms Access 2007,==问题=== 我在3个表上使用了一个左连接SQL表达式。尝试运行MS ACCESS 2007时,我从中收到一个意外错误“不支持联接表达式” ==详细信息=== 这些桌子都是连在一起的 家长:处于最高级别 孩子1:父母的孩子 子女2:父母的子女 孙辈1:孩子的孩子1 这是导致错误的SQL表达式: SELECT * FROM ((grandchild1 AS gc LEFT JOIN child1 AS c1 ON gc.child1_id=c1.id) LEFT JO
- 家长:处于最高级别
- 孩子1:父母的孩子
- 子女2:父母的子女
- 孙辈1:孩子的孩子1
SELECT *
FROM ((grandchild1 AS gc
LEFT JOIN child1 AS c1 ON gc.child1_id=c1.id)
LEFT JOIN parent AS p ON c1.parent_id=p.id)
LEFT JOIN child2 AS c2 ON (p.id=c2.parent_id
AND c2.start<=gc.time AND gc.time<=c2.stop)
选择*
FROM((1)作为gc
在gc.child1上将child1作为c1左连接(id=c1.id)
在c1上以p的形式左键连接父项。父项(id=p.id)
左连接child2作为c2打开(p.id=c2.parent\u id
和c2.start通常,您编写的连接如下:
SELECT * FROM grandchild1 AS gc
LEFT JOIN child1 AS c1 ON gc.child1_id=c1.id
LEFT JOIN parent AS p ON c1.parent_id=p.id
LEFT JOIN child2 AS c2 ON (p.id=c2.parent_id AND c2.start<=gc.time AND gc.time<=c2.stop)
从1中选择*作为gc
将child1作为c1在gc上左键联接。child1_id=c1.id
在c1上以p的形式左键连接父项。父项id=p.id
左键连接child2作为c2 ON(p.id=c2.parent_id和c2.start查看
看起来有点特别,在ON子句中只允许一个操作。
另外,对于access 2007,您必须嵌套您的联接。
此外,我认为日期范围应该在WHERE子句中
试试这个:
SELECT *
FROM grandchild1 AS gc
LEFT JOIN (
child1 as C1 LEFT JOIN (
parent as P LEFT JOIN child2 as C2 ON P.id = C2.parent_id
) ON c1.parent_id = P.id
) ON gc.child1_id = C1.id
WHERE
c2.start <= gc.time AND gc.time <= c2.stop
选择*
从1开始作为gc
左连接(
child1作为C1左联接(
父对象作为P左连接子对象2作为P.id=C2.parent\u id上的C2
)在c1.parent_id=P.id上
)关于gc.child1_id=C1.id
哪里
c2.start在非等联接中,表的顺序必须相同。而不是这样:
c2.start<=gc.time AND gc.time<=c2.stop
中间是包含双方的,所以我认为它完全等同于您最初的标准
尽管如此,我认为问题在于你定义的连接有三个条件,其中一个适用于一对表,另外两个适用于另一对表。你的第一个条件,p.id=c2.parent_id,将c2连接到p,而你的第二对非相等条件将c2和gc连接起来。这些类型的连接是非常复杂的y
我建议使用Access QBE将连接定义为相等连接,然后调整连接的SQL使其成为非相等连接
或者,在WHERE子句中应用日期/时间条件可能更简单,即作为隐式联接。使用WHERE条件并保留ON条件,以实现其目的,即指定如何联接表而不是过滤数据。您的方法也更难读取,并且不总是适用于r实例将方法3的WHERE条件移动到ON子句中,并亲自查看
drop table if exists t1;
create table t1(id int unsigned not null primary key);
drop table if exists t2;
create table t2(id int unsigned not null primary key);
insert into t1 (id) values (1),(2),(3),(5),(4),(6);
insert into t2 (id) values (2),(4),(6);
-- method 1:
select t1.id from t1 where id not in (select id from t2);
-- method 2:
select t1.id from t1 where not exists (select id from t2 where t1.id = t2.id);
-- method 3:
select
t1.id
from
t1
left outer join t2 on t1.id = t2.id
where
t2.id is null;
Access/Jet/ACE需要参数。Access QBE会将它们放在需要的位置。忽略它们,它会抱怨,否则您可能无法获得预期的结果。谢谢,但是的,我在其他表达式中尝试了这个方法,一开始没有在每个连接周围加括号,但Access似乎不接受它…我想这是您的访问谢谢David。使用QBE正如您所说,让access构造连接提供了解决方案。我尝试用左连接替换它使用的内部连接,但这导致错误再次出现。它似乎也不喜欢我将ON子句放在括号之间(我认为我实际上在帮助它)但是它似乎在ON子句中的表顺序方面没有问题。我想使用内部联接确实更有意义,所以我会坚持下去。我很高兴它被解决了。这确实让我感到QBE的巨大优势。它确实可以让您更轻松地获得Jet/ACE的正确语法。谢谢您的建议。我我应该使用这个,但是我加入的表是在FROM子句中创建一个或多个表,所以我真的不能使用WHERE子句(很抱歉,我的示例没有给出,因为我试图保持它的简单性)“不能”可能不是真的。我想这会很不方便,因为大多数显式连接都可以转换为等价的WHERE子句(隐式连接),而且大多数数据库引擎都会完全相同地优化等价语句,我不相信这一点。我想检查查询优化以确定(Google Jet SHOWPLAN将了解如何进行优化)。
c2.start<=gc.time AND gc.time<=c2.stop
c2.start<=gc.time AND c2.stop>=gc.time
gc.time>=c2.start AND gc.time<=c2.stop
gc.time BETWEEN c2.start AND c2.stop
drop table if exists t1;
create table t1(id int unsigned not null primary key);
drop table if exists t2;
create table t2(id int unsigned not null primary key);
insert into t1 (id) values (1),(2),(3),(5),(4),(6);
insert into t2 (id) values (2),(4),(6);
-- method 1:
select t1.id from t1 where id not in (select id from t2);
-- method 2:
select t1.id from t1 where not exists (select id from t2 where t1.id = t2.id);
-- method 3:
select
t1.id
from
t1
left outer join t2 on t1.id = t2.id
where
t2.id is null;