表:
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.难道子查询就不能用在左连接里吗

解决方案 »

  1.   

    select *
    from 
    temp7 left outer  join temp8 on temp7.age2=temp8.age2 inner join (select 1 as f) s on temp8.age2=s.f
      

  2.   

    select *
    from (select 1 f) s,
    temp7 left join temp8 on temp7.age2=temp8.age2 
    where temp8.age2=s.f--改成where
      

  3.   

    join 之后的 on 看来是不能  and 的
    要么你把这三个表一次join起来
    要么就用where补足条件
      

  4.   

    以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 (select '6380' f) a ,stores b left join sales c on b.stor_id=c.stor_id where c.stor_id=a.f
      

  5.   

    放在where后面肯定是可以的,不过那样就影响了结果的正确性了,导致本来主表中可查到的查不到了,为什么放在left join里就不行了呢?wgzaaa能讲讲具体的原因吗
      

  6.   

    为什么放在left join里就不行了呢?
    ------------
    行的。以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 
      

  7.   

    不是这样的,你写的和我不一样,你是把a作主表了,而我只是把a.f作为主表的一个条件,没有把它作主表。
      

  8.   

    噢,那用寒泉的方法呢? lwl0606(寒泉) ( ) 信誉:100    Blog   加为好友  2007-04-29 09:17:01  得分: 0  
     
     
       select *
    from 
    temp7 left outer  join temp8 on temp7.age2=temp8.age2 inner join (select 1 as f) s on temp8.age2=s.f  
     
      

  9.   

    innser join好用,不过它相当于where temp8.age2=s.f吧
      

  10.   

    还是不符合我的要求,我现在是:
    select *
    from 
    temp7 
    left join temp8 on temp7.age2=temp8.age2 and temp8.age2=(select top 1 ... from ...)
    感觉这样效率有点低,因为每行记录都要调用一次子查询,应该有更高效的办法解决这个问题吧。再加点分,欢迎继续讨论
      

  11.   

    to paoluo:
      我子查询是为了求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.
      

  12.   

    (select 1 f) s 只跟temp8有关联必须先处理,作一次子查询select *
    from temp7
    left join 
    (select * from temp8,(select 1 f) s where temp8.age2=s.f) as temp88 on temp7.age2=temp88.age2
      

  13.   

    这样如果不行,就做右关联.
    select * from
    (select * from temp8,(select 1 f) s where temp8.age2=s.f)
    as temp88 
    right join
    temp7 on temp7.age2=temp88.age2
      

  14.   

    --搂主的查询效率低,有点怪
    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
    这样大气多了.
      

  15.   

    --不好意思,写错了,exists查询返回都是True 
    --还是用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
      

  16.   

    to sky9705:
      你用exist这种写法比select top 1效率高吗?为什么左连接里不可以引用子from后面的子查询呢?原理上讲不通吗
      

  17.   

    To:fxbird(昨天晚上我可能死了)
    -----------------------------
    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 ...)
      

  18.   

    可以,不知道你这么写是什么意思但根据你原来SQL的结果,应该这么写
    select *
    from (select 1 f) s cross join temp7
     left join temp8 on temp7.age2=temp8.age2 and temp8.age2=s.f
      

  19.   

    如果是单一数值就不要做表查询了
    declare @s int set @s=1
    select *,@s  as f
    from   temp7
     left join temp8 on temp7.age2=temp8.age2 and temp8.age2= @s
      

  20.   

    to sp4(1):
      我的意思就是先进行一个子查询,查出一个值来作为另外一个表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的时候,子查询为什么不能在左连接里被引用呢?
      

  21.   

    如果不是真实的环境下,很难理解楼主的意图=(select top 1 ... from ...)如果跟另外两个表没有关系,直接作为变量不就好了吗?如果是跟查询的数据有关的,可以考虑用函数来优化。这个问题本身不是左联接和子查询的问题,而是联接的ANSI写法和一般写法不能混用的问题。如果楼主关心效率,只要不是相关子查询,数据库会优化成联接的,不用担心。
      

  22.   

    select top 1 ... from ...)只是为了举个例子,实际是从一个表中查询的,而且这个值在后面的查询中是要用的,这里我查询的实际是一个仓库编号,在后面的子查询中要用它,否则每次都要写个子查询来提供这个值。"这个问题本身不是左联接和子查询的问题,而是联接的ANSI写法和一般写法不能混用的问题"这该怎么理解?
      

  23.   

    楼主的概念不大清楚,楼主一直在问为什么子查询不能在左连接里被引用,其实bill告诉的你很明白了,‘The column prefix 's' does not match with a table name or alias name used in the query.’,你引用的既不是一个表名也不是一个被查询使用过的别名。你想要作的是左连接,而这是一种集合运算,换句话说它要求‘left join’的左边和右边都必须是数据集合(比如表或子查询),看你的语句
    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 ...."的语法虽然现在仍然支持,那只是为了向后兼容。
      

  24.   

    惭愧,其实人家说的很明白,'这个问题本身不是左联接和子查询的问题,而是联接的ANSI写法和一般写法不能混用的问题' ,错误的原因就是你把两种写法搞混了。我写的就算给人家当注解吧,呵呵
      

  25.   

    to sjlion:
      left join左边只是temp7,怎么还有s呢,那个又不起作用。select 1 f已经起成s了,怎么还说没有这样的名字?什么情况下能算有?你理解sp4的说法吗?
      

  26.   

    我是说在‘left join’左边到from之间!当然有s了。换一种表述方法和你说吧,加个括号你应该能搞明白。((select 1 f) s,temp7) left join (temp8)这其实是分析器'看到的'你的表述方式,而这就像sp4所说,你把'联接的ANSI写法和一般写法搞混了’,对于'联接的ANSI写法'来说,用在on条件中的数据必须是互相join的数据集中的数据。你写的
    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乘!你对运算顺序以及这个运算的边界的理解是错误的!
      

  27.   

    select *
    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还没算出来呢,它的列怎么能被引用?
    --以上的表述极不严谨,只是希望能帮助你理解
      

  28.   

    SELECT *
    FROM
    temp7 LEFT JOIN temp8 ON temp7.age2=temp8.age2 INNER JOIN (SELECT 1 AS f) s ON temp8.age2=s.f
      

  29.   

    to sjlion:
      我才知道原来left join前面的表都是作为主表的,我原以为只是temp7是主表呢,对左连还是不太明白。请问是sqlserver还是所有的数据库都是先进行left join然后再与其它表相关联吗?
      

  30.   


    我就根据你原来的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
      

  31.   

    晕。楼主不是因为left join问题写错的吧?
      

  32.   

    真晕了,这个问题我以前居然回复过,呵呵
    有个xd解释的不错,楼主弄清楚left join就明白了,估计理解问题,你写的错了。
      

  33.   

    又看到了,再说两句,个人见解,欢迎指正
    其实问题的根本是查询的次序问题,大家一般都认为是从左到右,如果要改变顺序就要用括号.
    但事实上并非一律从左到右,还有嵌套,楼主的问题就是一个,
    (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后就是外层的条件,它倒可以引用内层的数据
     
      

  34.   

    simonhehe(流氓会武术,谁也挡不住)

    rookie_one(猩猩会武术,流氓挡不住) ??
    属于严重挑衅行为!!!
      

  35.   

    这里没有挑衅承认了你改where的功劳,也承认了改cross那君的功劳,倒是另一贴子我刚刚说了你的贴子和人家的一样,时间又隔那么久。
      

  36.   

    select *
    from temp7 left join temp8 on temp7.age2=temp8.age2 
    inner join (select 1 f) on temp8.age2=s.f
      

  37.   

    to fxbird:
    wzgaaa说的基本正确,你能看懂就OK了