一个Select 的条件筛选优先问题

$扫地僧$ 2008-03-19 09:06:47
问题如下:
create table T
(
dt varchar(10)
)



insert T select null
insert T select ''
insert T select '2003-07-01'
insert T select '2004-01-05'
insert T select 'SDS'

--这样写是没问题的!!
select dt,Days
from (select dt,datediff(dd,'2003-07-01',dt) as Days from T where ISDate(dt)=1) Temp_A

--但是要是这样写

select dt,Days
from (select dt,datediff(dd,'2003-07-01',dt) as Days from T where ISDate(dt)=1) Temp_A
where Days>=0
就会提示 :
服务器: 消息 241,级别 16,状态 1,行 1
从字符串转换为 datetime 时发生语法错误。

我不明白 为什么会这样!!
按道理我是先把是日期类型的排出了的阿!!

麻烦那位大侠给解释一下 SQL server 里面的 where 语句的筛选原理 !谢谢!!


...全文
643 35 打赏 收藏 转发到动态 举报
写回复
用AI写文章
35 条回复
切换为时间正序
请发表友善的回复…
发表回复
lyd963 2008-03-20
  • 打赏
  • 举报
回复
mark 学习一下
lhsxsh 2008-03-20
  • 打赏
  • 举报
回复
先执行的WHERE条件是:datediff(dd,'2003-07-01',dt) > =0
being21 2008-03-20
  • 打赏
  • 举报
回复
参与观看!
回帖是一种美德!传说每天回帖即可获得 10 分可用分!
wzjpsq 2008-03-20
  • 打赏
  • 举报
回复
学习
shenzilei 2008-03-20
  • 打赏
  • 举报
回复
SQL code你可以看SQL的【执行计划】,经过SQL查询器的自动优化后,
在WHERE语句中它是先执行:datediff(dd,'2003-07-01',dt)
再执行:ISDate(dt)=1 这样就会提示【从字符串转换为 datetime 时发生语法错误。】
你应该告诉SQL查询器你要操作的先后顺序。
改成:
select dt,Days from (select dt,datediff(dd,'2003-07-01',dt) as Days from T where ISDate(dt)=1) Temp_A
where (case when ISDate(dt)=1 then Days else
xiaomeixiang 2008-03-19
  • 打赏
  • 举报
回复
先执行的WHERE条件是:datediff(dd,'2003-07-01',dt) >=0
xiaomeixiang 2008-03-19
  • 打赏
  • 举报
回复
乌龟的方法不笨啊,这样就不会报错,可以查到语句的执行计划:

select dt,Days from (select dt,datediff(dd,'2003-07-01',dt) as Days from T where ISDate(dt)=1) Temp_A where Days> =0
|--Compute Scalar(DEFINE:([Expr1004]=datediff(day,'2003-07-01 00:00:00.000',CONVERT_IMPLICIT(datetime,[ERPDATA].[dbo].[T].[dt],0))))
|--Filter(WHERE:(isdate(CONVERT_IMPLICIT(nvarchar(10),[ERPDATA].[dbo].[T].[dt],0))=(1)))
|--Table Scan(OBJECT:([ERPDATA].[dbo].[T]), WHERE:(datediff(day,'2003-07-01 00:00:00.000',CONVERT_IMPLICIT(datetime,[ERPDATA].[dbo].[T].[dt],0))>=(0)))
xiaoku 2008-03-19
  • 打赏
  • 举报
回复
顶300分.
gahade 2008-03-19
  • 打赏
  • 举报
回复
楼主讨论的是语句的优化顺序,我学习.

如果是日期型的要用datetime,不要用字符型
dawugui 2008-03-19
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 JiangHongTao 的回复:]
引用 5 楼 dawugui 的回复:
错在这个:insert T select 'SDS'
其他没问题.

看来乌龟还是比较笨,LZ是特意增加那条记录用于测试出错的,主要问的是错误原因,而比试错误的地方。
另:比较同意16L的,SQL 的优化机制使得我们的SQL语句缺乏语法保障。
[/Quote]
乌龟不是比较笨,是非常笨.
$扫地僧$ 2008-03-19
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 dawugui 的回复:]
错在这个:insert T select 'SDS'
其他没问题.
SQL codecreatetableT (dtvarchar(10))insertTselectnullinsertTselect''insertintoTvalues('2003-07-01')insertintoTvalues('2004-01-05')--insert T select 'SDS'goselectdt,datediff(dd,'2003-07-01',dt)asDaysfromTwhereISDate(dt)=1/*dt Days
---------- -----------
2003-07-01 0
2004-01-05 188*/select*from(selectdt,datediff(dd,'2003-07-01',dt)asDay…
[/Quote]

insert T select 'SDS'
是我故意加上去 !!

我当然知道 这不是时间类型
bote_china 2008-03-19
  • 打赏
  • 举报
回复
试了一下,没有楼主所说的错误
yms_wangxm 2008-03-19
  • 打赏
  • 举报
回复
凑热闹的
zhuyx808 2008-03-19
  • 打赏
  • 举报
回复
分是比较多哈
肥胖的柠檬 2008-03-19
  • 打赏
  • 举报
回复
上面的也以说明了
也引用一下我们板主查询优化器对查询条件顺序的影响的示例:
--测试表及数据
CREATE TABLE tb(Col varchar(10))
INSERT tb SELECT '1900-1-1'
UNION ALL SELECT '19aa-1-1'
GO

SELECT * FROM tb
WHERE ISDATE(Col)=1
AND Col<GETDATE()
GO

--建立索引
CREATE INDEX IDX_tb_Col ON tb(Col)
GO

SELECT * FROM tb
WHERE ISDATE(Col)=1
AND Col<GETDATE()
GO

--删除测试
DROP TABLE tb

索引影响查询条件顺序
JiangHongTao 2008-03-19
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 dawugui 的回复:]
错在这个:insert T select 'SDS'
其他没问题.
[/Quote]
看来乌龟还是比较笨,LZ是特意增加那条记录用于测试出错的,主要问的是错误原因,而比试错误的地方。
另:比较同意16L的,SQL 的优化机制使得我们的SQL语句缺乏语法保障。
xiaoliaoyun 2008-03-19
  • 打赏
  • 举报
回复
SQL 做了优化,它的优化是基于成本,不是基于语法...下面的帖子有讨论
http://topic.csdn.net/u/20071210/10/b7cfec7a-080b-4a30-b62a-92c987d3bcdd.html
wzy_love_sly 2008-03-19
  • 打赏
  • 举报
回复
create table T
(
dt varchar(10)
)

insert T select null
insert T select ''
insert T select '2003-07-01'
insert T select '2004-01-05'
insert T select 'SDS'

select dt,Days from (
select dt,
case when isdate(dt)=1 then datediff(dd,'2003-07-01',dt) end as Days from t
) Temp_A where Days> =0


dt Days
2003-07-01 0
2004-01-05 188

直接看执行计划,表扫描先用条件datediff,筛选器才执行 isdate,
感觉有点象函数的优先级别,就算增加不是日期类型的数据,还是不先执行isdate,sql优化问题,不智能
-狙击手- 2008-03-19
  • 打赏
  • 举报
回复
查询优化成先执行datediff()了,所以报错
kelph 2008-03-19
  • 打赏
  • 举报
回复
select dt,Days  from (select dt,datediff(dd,'2003-07-01',dt) as Days from T ) Temp_A
where (case when ISDate(dt)=1 then Days else -1 end )>=0
加载更多回复(15)

34,587

社区成员

发帖
与我相关
我的任务
社区描述
MS-SQL Server相关内容讨论专区
社区管理员
  • 基础类社区
  • 二月十六
  • 卖水果的net
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧