===问题===
我在3个表上使用LEFT JOIN,SQL表达式。当我尝试运行它时,我从MS ACCESS 2007收到意外错误“不支持JOIN表达式”。
===细节===
这些表都已连接
这是导致错误的SQL表达式:
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)
奇怪的是,我在“ON”子句中只替换了其中一个布尔表达式为TRUE的以下表达式确实被接受了:
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 (TRUE
AND c2.start<=gc.time AND gc.time<=c2.stop)
===问题===
=== solution ===(感谢David-W-Fenton)
SELECT *
FROM ((grandchild1 AS gc
INNER JOIN child1 AS c1 ON gc.child1_id=c1.id)
INNER JOIN parent AS p ON c1.parent_id=p.id)
INNER JOIN child2 AS c2 ON (p.id=c2.parent_id)
AND (c2.start<=gc.time) AND (gc.time<=c2.stop)
答案 0 :(得分: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)
(注意缺少的parens。)
关于EXISTS,也许这是一个Access限制? MySQL很高兴在ON子句中有一个EXISTS。
答案 1 :(得分:1)
在非equi连接中,您必须使用相同的顺序。而不是:
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
您也可以测试BETWEEN是否有效:
gc.time BETWEEN c2.start AND c2.stop
BETWEEN双方都是包容性的,所以我认为它完全等同于你原来的标准。
所有这一切,我认为问题在于您定义了一个具有三个条件的连接,其中一个适用于一对表,另外两个适用于另一对表。你的第一个条件,p.id = c2.parent_id,将c2加到p,而你的第二对非equi条件加入c2和gc。这些类型的连接很棘手。
我建议使用Access QBE将连接定义为equi-joins,然后调整连接的SQL以使其成为非equi连接。
或者,在WHERE子句中应用日期/时间标准可能更简单,即作为隐式连接。
答案 2 :(得分:0)
在ON子句中只允许一个操作,看起来有点具体。 此外,它看起来像访问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
答案 3 :(得分:0)
使用WHERE条件并保留ON条件以达到预期目的,即指定如何连接表而不是用于过滤数据。您的方法也更难以阅读,并且不总是工作,例如将方法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;