这一段是数据生成语句
create table t2(aid int identity(1,1) primary key,
fid int,
pid int,
ftype int,
fname varchar(50),
fvalue nvarchar(200)
)
declare @line_id int;
declare @xml nvarchar(1000);
declare @doc_int int;
set @xml='<row dir_desc="" dir_name="Test3" dir_type="2" />';
exec sp_xml_preparedocument @doc_int output,@xml;
insert into t2 (fid,pid,ftype,fname,fvalue)
select [id] as fid,parentid as pid,nodetype as ftype,
localname as fname,[text] as fvalue from
openxml(@doc_int,'/row[@*]',1)
where nodetype>1;
exec sp_xml_removedocument @doc_int;
问题是
select a1.fname,a2.fvalue
from t2 a1
left join t2 a2 on a1.fid=a2.pid
where a1.ftype=2 and a2.ftype=3
只能得到2条记录
我要的结果是
select a1.fname,isnull(a2.fvalue,'') as fvalue
from t2 a1
left join t2 a2 on a1.fid=a2.pid and a2.ftype=3
where a1.ftype=2
------解决思路----------------------
and a2.ftype=3是必须的条件,其实相当于a2和a1内连接
select a1.fname,a2.fvalue
from t2 a1
left join t2 a2 on a1.fid=a2.pid
where a1.ftype=2 and a2.ftype=3
and a2.ftype=3非必要条件,可以查询出不满足a1.fid=a2.pid and a2.ftype=3条件的记录。
select a1.fname,isnull(a2.fvalue,'') as fvalue
from t2 a1
left join t2 a2 on a1.fid=a2.pid and a2.ftype=3
where a1.ftype=2
------解决思路----------------------
这个详细的,你有空去看下,SQL查询的逻辑顺序,你可很明了的了解处理方式和顺序
这里针对你的问题,我觉得可以这样说,ON和WHERE的区别本质在内连接和外连接的区别,如果你的连接不是左连接而是内连接,那么,条件放到ON和放到WHERE是一样的
而外连接,如左连接,左连接分为左输入和右输入,SQL查询将两个输入根据ON后面的条件过滤出一个积,然后再把左输入存在的而右输入不存在的加入进来,然后再执行WHERE条件过滤
我的描述可能不是完全官方标准,但是,接近了,大体意思就是这样,SQL查询的逻辑处理顺序。
因此,从上面我们可以推出,a2.ftype=3放在WHERE上,过滤的是最终的结果,而放到左连接只取到限制右输入的作用
------解决思路----------------------
2楼正解。
on a1.fid=a2.pid where a1.ftype=2 and a2.ftype=3 过滤最终结果。
on a1.fid=a2.pid and a2.ftype=3 where a1.ftype=2 限制又输入。
------解决思路----------------------
不是,理解SQL查询可以从逻辑上和物理上看,逻辑上肯定不是,物理上对于左连接也不是
------解决思路----------------------
where 是结果集的一个条件过滤,
on 是对联合多张表的条件关联。
on 的在时间顺序要优先于 where 。
------解决思路----------------------
以下步骤显示 SELECT 语句的处理顺序
FROM
ON
JOIN
WHERE
GROUP BY
WITH CUBE 或 WITH ROLLUP
HAVING
SELECT
DISTINCT
ORDER BY
TOP
------解决思路----------------------
这是个过程,得适应
(这是病,得治)

------解决思路----------------------
在SQL2005就废弃了,要支持需要改数据库兼容性为80以前的版本
*= 和 =* 外部联接运算符
使用 FROM 子句的 JOIN 语法。
------解决思路----------------------
当改了兼容性后,新版本的语句会不支持,这你要自己考虑得失
------解决思路----------------------
这段我很有印象
JOIN 的时候,会先用ON过滤不合适的,然后再JOIN,最后再WHERE,这是正常的处理顺序,即逻辑上的处理顺序,但是,SQL查询优化在内连接的时候,会提前把WHERE的条件带进去过滤,因为这样的结果一样,而且会更有效率,而是物理处理上真正的处理顺序
但是,如果是外连接,提前把WHERE带入过滤得出的结果是不对的,所以左外连接的时候,不会提前把右输入的过滤条件带进去,只会在JOIN后进行筛选,然后,左输入存在而右输入不存在的情况,会把左输入的数据加上右输入的全部设置为NULL加到JOIN后的积,这时在进行WHERE的筛选,不符合条件及涉及NULL的判断全部是FALSE,全部会被过滤掉
------解决思路----------------------
只有 inner join 才可以等价看成先筛选出子集、再连接出结果。
其实所有的 join 你都应该看成遍历游标的双层循环:
select a1.fname,a2.fvalue
from t2 a1
left join t2 a2 on a1.fid=a2.pid
where a1.ftype=2 and a2.ftype=3
外层游标 SELECT * FROM t2 a1 WHERE a1.ftype=2,循环:
内存游标 SELECT * FROM t2 a2 WHERE a1.fid=a2.pid,由于是左连接,不加条件 a2.ftype
如果 a2 为空,输出有 a1 无 a2 的记录;
如果 a2.ftype=3,输出 a1、a2 都有的记录;
如果 a2.ftype<>3,不输出记录。
select a1.fname,isnull(a2.fvalue,'') as fvalue
from t2 a1
left join t2 a2 on a1.fid=a2.pid and a2.ftype=3
where a1.ftype=2
外层游标一样是 SELECT * FROM t2 a1 WHERE a1.ftype=2,循环:
内存游标 SELECT * FROM t2 a2 WHERE a1.fid=a2.pid and a2.ftype=3,由于是on条件,可以加在这里
如果对应 a2.pid 本来就没记录,内游标为空,输出有 a1 无 a2 的记录;
如果对应 a2.pid 的记录 a2.ftype=3,一样输出 a1、a2 都有的记录;
如果对应 a2.pid 的记录全部 a2.ftype<>3,内游标为空,输出有 a1 无 a2 的记录。