此声明有效:
DECLARE @variable_name INT
SET @variable_name = (SELECT DATEPART(DAYOFYEAR, GETDATE()))
SELECT *
FROM artists
WHERE SUBSTRING(DOB, 0, 5) > '1900'
AND CONVERT(INT, DATEPART(DAYOFYEAR, DOB)) = @variable_name
这个不起作用:
SELECT *
FROM artists
WHERE SUBSTRING(DOB, 0, 5) > '1900'
AND CONVERT(INT, DATEPART(DAYOFYEAR, DOB)) =
(SELECT CONVERT(INT, datepart(DAYOFYEAR, getdate())))
它返回错误
Msg 242,Level 16,State 3,Line 1
将varchar数据类型转换为日期时间数据类型会导致超出范围的值。
这个有效
SELECT *
FROM artists
WHERE DOB IS NOT NULL
AND SUBSTRING(DOB, 0, 5) > '1900'
AND convert(int, DATEPART(DAYOFYEAR, DOB)) = '100'
今天恰好是一年中的第100天
我不明白为什么,我正在使用SQL Server 2008。
该列设置为varchar(10)
。我的日期可以追溯到1700年的
表中的日期格式为
1930-04-10
YYYY-MM-DD
我可以将两个查询放在同一个窗口中,一次突出显示并运行一个查询对同一个数据集。并得到上述结果。
答案 0 :(得分:1)
在两个查询中,您正在检查两个条件:
SUBSTRING(DOB, 0, 5) > '1900'
和
CONVERT(INT, DATEPART(DAYOFYEAR, DOB)) = some integer;
DBMS决定首先检查哪一个。显然,在您的第一个查询中,DBMS首先检查第一个表达式,从而排除了一些无法用DOB
转换的DATEPART
。但是第二个查询首先检查第二个条件,并且尝试转换某个值失败。
我的建议:您最好的选择是更改表格并将DOB存储为DATETIME2
而不是VARCHAR(10)
。
如果由于某种原因无法做到这一点,可以使用子查询(派生表)强制第一个条件优先于第二个条件:
select *
from artists
from
(
select *
from artists
where substring(dob, 1, 4) > '1900'
) after_1900
where datepart(dayofyear, dob) = datepart(dayofyear, getdate());
这有效(希望如此),但并不完全正确。例如,DOB
仍然可以包含无效日期,例如'2016-XY- ??'或者只是'2016-02-30'。在DATEPART
表达式中,您将DOB
视为DATETIME
而不是select dob, name
from
(
select convert(datetime2, dob + ' 00:00:00', 120) as dob, name
from artists
from
(
select dob, name
from artists
where dob like '[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]'
) valid_data_strings
) converted
where datepart(year, dob) > 1900
and datepart(dayofyear, dob) = datepart(dayofyear, getdate());
。发生隐式转换,很容易失败。
这是一个查询,首先检查正确的日期格式,以及明确的字符串到日期转换:
Method, Classifier, Accuracy
M1, C1, 2.4
M1, C1, 2.3
M1, C1, 6.4
M1, C2, 0.4
M1, C2, 1.3
M1, C2, 6.8
M1, C3, 3.4
M1, C3, 2.7
M1, C3, 2.4
M2, C1, 0.4
M2, C1, 2.8
M2, C1, 3.4
M2, C2, 7.4
M2, C2, 2.3
M2, C2, 6.5
M2, C3, 1.4
M2, C3, 2.7
M2, C3, 7.4
M3, C1, 2.0
M3, C1, 1.3
M3, C1, 7.2
M3, C2, 8.4
M3, C2, 1.3
M3, C2, 9.8
M3, C3, 3.9
M3, C3, 3.7
M3, C3, 0.9
尽管如此,这并不能解决2月30日的问题。我不认为有一种简单的方法来检测有效的日期字符串,然后只考虑这些记录。可能,是的,但肯定有一些工作与所有闰年逻辑需要。
如上所述,改变表格设计要容易得多。
答案 1 :(得分:0)
答案很简单,但仍然很奇怪。
此声明不起作用
SELECT * FROM artists WHERE SUBSTRING(DOB, 0, 5) > '1900'
AND CONVERT(INT, DATEPART(DAYOFYEAR, DOB)) = (SELECT CONVERT(INT, datepart(DAYOFYEAR, getdate())))
这个确实
SELECT * FROM artists WHERE SUBSTRING(DOB, 0, 5) > '1900'
AND CONVERT(INT, DATEPART(DAYOFYEAR, DOB)) = (CONVERT(INT, datepart(DAYOFYEAR, getdate())))
通过从获取当前日期部分中删除Select,该语句会生动,这只能意味着添加“Select”(实际上没有区别),改变了优先顺序,这在一种错综复杂的方式。但我认为这是一个错误。