表:
temp7(age--int,age2--int)
temp8(age2--int,name--varchar(50))select *
from (select 1 f) s,
temp7 left join temp8 on temp7.age2=temp8.age2 and temp8.age2=s.f我将temp8左连接到temp7时,并引用了子查询s的字段,结果报错如下:
The column prefix 's' does not match with a table name or alias name used in the query.难道子查询就不能用在左连接里吗
temp7(age--int,age2--int)
temp8(age2--int,name--varchar(50))select *
from (select 1 f) s,
temp7 left join temp8 on temp7.age2=temp8.age2 and temp8.age2=s.f我将temp8左连接到temp7时,并引用了子查询s的字段,结果报错如下:
The column prefix 's' does not match with a table name or alias name used in the query.难道子查询就不能用在左连接里吗
from
temp7 left outer join temp8 on temp7.age2=temp8.age2 inner join (select 1 as f) s on temp8.age2=s.f
from (select 1 f) s,
temp7 left join temp8 on temp7.age2=temp8.age2
where temp8.age2=s.f--改成where
要么你把这三个表一次join起来
要么就用where补足条件
------------
行的。以sqlserver中的pubs库中为环境,试验如下,结果均正常。select * from (select '6380' f) a left join stores b on a.f=b.stor_id left join sales c on b.stor_id=c.stor_id
select *
from
temp7 left outer join temp8 on temp7.age2=temp8.age2 inner join (select 1 as f) s on temp8.age2=s.f
select *
from
temp7
left join temp8 on temp7.age2=temp8.age2 and temp8.age2=(select top 1 ... from ...)
感觉这样效率有点低,因为每行记录都要调用一次子查询,应该有更高效的办法解决这个问题吧。再加点分,欢迎继续讨论
我子查询是为了求temp8.age2的值,这个跟具体数据无关。你要是非要看数据,那么用下面这个:
temp7(age,age2)
1 1
1 2
1 3temp8(age2,name)
1 1-1
1 1-2
2 2-1
3 3-1
age,age2是整形,name是varchar.
from temp7
left join
(select * from temp8,(select 1 f) s where temp8.age2=s.f) as temp88 on temp7.age2=temp88.age2
select * from
(select * from temp8,(select 1 f) s where temp8.age2=s.f)
as temp88
right join
temp7 on temp7.age2=temp88.age2
select *
from
temp7
left join temp8 on temp7.age2=temp8.age2 and temp8.age2=(select top 1 ... from ...)
第一:
你的意图里,想在left join时进行筛选来减少执行损耗,这很含糊,你必须先决定先left join,还是先筛选,所有的查询都是一步一步来的,temp8只跟 (select 1 f) s 关联,我相信先筛选再left join的效能要好的多,除非你left join的是主索引字段,不过你的Age2肯定不是索引.所以还是先筛选吧
第二:
temp8.age2=(select top 1 ... from ...)的这种写法有点怪,
类似的象select in 语句,除非在索引字段上用,否则跑的要死,性能很低.
第三:
根据作者意图,你的要求只是左外联temp8中,temp8与筛选表只要求存在关系判断
所以还有可以改进的地方:
select * from temp8 where exists(select * from 筛选表 where 筛选表.field1=temp8.field1 )
这样就不需要用=select top 1这么别扭,改成这样
select * from
(select * from temp8 where exists(select * from 筛选表 where 筛选表.field1=temp8.field1 )
)
as temp88
right join
temp7 on temp7.age2=temp88.age2
这样大气多了.
--还是用where子查询再右外联吧.select * from
(select * from temp8,(select 1 f) s where temp8.age2=s.f)
as temp88
right join
temp7 on temp7.age2=temp88.age2
你用exist这种写法比select top 1效率高吗?为什么左连接里不可以引用子from后面的子查询呢?原理上讲不通吗
-----------------------------
Linbaba(sky)已经回复过了
exists这种写法是错的,每次都是true--为什么左连接里不可以引用子from后面的子查询呢?
原理上应该可以,之前我试几次左联没成,所以改右联,复杂的查询放前面,反正结果是一样,所以没去研究.至于用top 1的写法是否执行效率,不懂select *
from
temp7
left join temp8 on temp7.age2=temp8.age2 and temp8.age2=(select top 1 ... from ...)
这句最后一个条件要用where,否则会出错select *
from
temp7
left join temp8 on temp7.age2=temp8.age2 where temp8.age2=(select top 1 ... from ...)
select *
from (select 1 f) s cross join temp7
left join temp8 on temp7.age2=temp8.age2 and temp8.age2=s.f
declare @s int set @s=1
select *,@s as f
from temp7
left join temp8 on temp7.age2=temp8.age2 and temp8.age2= @s
我的意思就是先进行一个子查询,查出一个值来作为另外一个表temp8.age2的查询条件,你的这个:
select *
from (select 1 f) s cross join temp7
left join temp8 on temp7.age2=temp8.age2 and temp8.age2=s.f
是好用的,但我更想知道的是,不用cross的时候,子查询为什么不能在左连接里被引用呢?
select *
from (select 1 f) s,
temp7 left join temp8 on temp7.age2=temp8.age2 and temp8.age2=s.f‘left join’ 右边是temp8,没问题,可它的左边和from之间是 "(select 1 f) s,temp7",这个东东既不是一个表,也不是一个子查询,你希望数据库引擎怎么‘理解’它?outer join?inner join? union ?无法解析当然会报错。
你问sp4为什么他的cross可以
"select *
from (select 1 f) s cross join temp7
left join temp8 on temp7.age2=temp8.age2 and temp8.age2=s.f"
依前所述,他'left join'的两边一边是"temp8"(表),另一边是"(select 1 f) s cross join temp7"(一个cross join而成的数据集合),所以可用。
至于你说的用'where'可以,那不过是因为用where的时候sql server会把所有from后边的多个数据集合之间的关系解析成一个一个的内连接,这个时候你的‘s’被当作一个单独的数据集合和其他的数据集合发生关系,当然是可以的了。不过bill早说过希望大家作连接运算时使用标准sql-99的语法,即join,至于类似 "from a,b,c where a.1=b.1 and b.1=c.1 and ...."的语法虽然现在仍然支持,那只是为了向后兼容。
left join左边只是temp7,怎么还有s呢,那个又不起作用。select 1 f已经起成s了,怎么还说没有这样的名字?什么情况下能算有?你理解sp4的说法吗?
select *
from (select 1 f) s,
temp7 left join temp8 on temp7.age2=temp8.age2 and temp8.age2=s.f,你自己都说了,s不起作用,准确的说这个'不起作用'其实说起来是对join运算不起作用,既然不起作用,你凭什么用人家?!‘s’是在连接运算之外的!
而一般写法,比如用where,是没有这么严格的要求的,
这也是‘猩猩会武术'让你写成
select *
from (select 1 f) s,
temp7 left join temp8 on temp7.age2=temp8.age2
where temp8.age2=s.f--改成where
的原因,这个时候,其实连接运算已经是一个经过运算后的数据集了,它和s是并列的,相当于
select *
from (select 1 f) s,
(select * from temp7 left join temp8 on temp7.age2=temp8.age2) t
where t.age2=s.f
或者
select *
from (select 1 f) s join
(select * from temp7 left join temp8 on temp7.age2=temp8.age2) t
on t.age2=s.f
(当然以上写法可能是错的,因为我不知道你的表结构)
明白?打个不恰当的比方,有个算式(a+b)*(c+d)=e,你却非要求a先和d加完了再和c乘!你对运算顺序以及这个运算的边界的理解是错误的!
from (select 1 f) s,
temp7 left join temp8 on temp7.age2=temp8.age2=s.f在这个语句中 's' 和 'temp7 left join temp8 on temp7.age2=temp8.age2' 他们是同一个层次的,他们互相之间可以连接等等做各种运算,整个运算时left join是最先进行的运算,而这个时候,s还没算出来呢,它的列怎么能被引用?
--以上的表述极不严谨,只是希望能帮助你理解
FROM
temp7 LEFT JOIN temp8 ON temp7.age2=temp8.age2 INNER JOIN (SELECT 1 AS f) s ON temp8.age2=s.f
我才知道原来left join前面的表都是作为主表的,我原以为只是temp7是主表呢,对左连还是不太明白。请问是sqlserver还是所有的数据库都是先进行left join然后再与其它表相关联吗?
我就根据你原来的SQL来修改一下
select *
from
(select 1 as f) s cross join temp7
left join temp8 on
temp7.age2=temp8.age2
and s.f=temp8.age2这样就可以了,楼主没有任何尾随条件,这样就没有问题,因为事实也确实是cross join
有个xd解释的不错,楼主弄清楚left join就明白了,估计理解问题,你写的错了。
其实问题的根本是查询的次序问题,大家一般都认为是从左到右,如果要改变顺序就要用括号.
但事实上并非一律从左到右,还有嵌套,楼主的问题就是一个,
(select 1 f) s,temp7 left join temp8 on temp7.age2=temp8.age2 and temp8.age2=s.fa left join b on a.x=b.x left join c on a.x=c.x 大家知道从左到右,但也可以嵌套
a left join b left join c on c.x=b.x on a.x=c.x 此时第一个on中不能出现a的内容(还没到外层)
楼主a,b的形式后跟 where 第二个and 改成where 就形成嵌套所以正确
cross后面不需要用on优于其它联接,所以 a cross b join c on b.x=c.x and a.x=b.x 成立
and 改where也可以
因为限定 a,b形式的是where 它无法插入到 join 中间,所以它始终是嵌套,并且是外层,导致不能在内层的条件引用外层的数据,改成where后就是外层的条件,它倒可以引用内层的数据
:
rookie_one(猩猩会武术,流氓挡不住) ??
属于严重挑衅行为!!!
from temp7 left join temp8 on temp7.age2=temp8.age2
inner join (select 1 f) on temp8.age2=s.f
wzgaaa说的基本正确,你能看懂就OK了