【问题标题】:SELECT Between dates almost workingSELECT 日期之间几乎可以工作
【发布时间】:2013-08-25 10:18:34
【问题描述】:

我的问题可能与SELECT 中的日期格式有关。

在一个 asp 文件中,我打开一个 ADO 记录集,希望检索位于 date1 (08/15/2013)date2 (08/22/2013) 之间的 MS SQL 表的行(即,从今天开始的前 7 天。)

SELECT 确实检索了适当的 2013 年行,但也检索了可追溯到 2012 年 8 月 15 日的行。

这里是选择:

oRS.Source = "SELECT * FROM aTable WHERE entry_Date BETWEEN '" & resultLowerDate & "' AND '" & resultCurrentDate & "' AND entry_Status <> 'INACTIVE'"

resultLowerDate = 08/15/2013 和 resultCurrentDate = 08/22/2013。

表格设置如下,resultCurrentDate = "08/22/2013":

entry_Status    entry_Date (varchar)    LastName    FirstName   SELECT Result
INITIAL     08/15/2012      Smith       Jim         YES
INACTIVE    08/21/2012      Green       Tom         no
INITIAL     08/22/2013      Jones       Mary            yes
FOLLOWUP    08/22/2013      Jones       Mary            yes
FOLLOWUP    08/22/2013      Brown       Sally           yes
FOLLOWUP    08/22/2013      Smith       Jim         yes

关于为什么INITIAL 08/15/2012 行与满足SELECT 查询的其他行一起被选中的任何想法?

【问题讨论】:

  • 为什么 entry_Date 是一个 varchar???
  • 如果@AaronBertrand 不会插入他自己的文章,我会的。 阅读Choosing the wrong data typemis-handling date/range queries。可能值得阅读整个不良习惯踢系列。它们都是正确的,如果每个人都阅读它们,Stackoverflow 上的问题就会少很多!

标签: sql-server-2008 date select


【解决方案1】:

停止在 VARCHAR 列中存储日期!并停止连接字符串,使用正确的参数。

很抱歉大喊大叫,但我们每天都会收到多个问题,其中人们出于某种未知且可能很愚蠢的原因使用了错误的数据类型,而这些正是它导致的问题。

这里的问题是您正在比较 字符串。试试:

"... WHERE CONVERT(DATETIME, entry_date, 101)" & _
     " >= CONVERT(DATETIME, '" & resultLowerDate & "', 101)" & _
" AND CONVERT(DATETIME, entry_date, 101)" & _
     " < DATEADD(DAY, 1, CONVERT(DATETIME, '" & resultCurrentDate & "', 101))"

或者更好的是,将 resultLowerDate 和 resultUpperDate 设置为 YYYYMMDD 格式,然后你可以说:

"... WHERE CONVERT(DATETIME, entry_date, 101) >= '" & resultLowerDate & "'" & _
" AND CONVERT(DATETIME, entry_date, 101) < DATEADD(DAY, 1, '" & resultCurrentDate & "'"

请注意,我使用开放式范围(>= 和

另请注意,此查询可能会失败,因为垃圾进入了您的列。它可以,因为您选择了错误的数据类型。我真正的建议是修复表格并使用DATEDATETIME 列。

【讨论】:

  • 我已经在这个问题上搁置了一段时间。但是,今天我已经审查了您的建议并采纳了您的建议。我已将相应的表格列修改为日期和时间类型。
  • @user2033850 太好了!迟到总比不到好。 :-)
【解决方案2】:

您的 entry_Date 列是 varchar 字段而不是实际日期这一事实是问题所在。如果您在选择期间将其转换为日期时间,您将获得预期的结果。

select *
from aTable
where cast(entry_Date as datetime) between '08/15/2013' and '08/22/2013'

Sql Fiddle link

【讨论】:

  • 如果用户使用 SET LANGUAGE BRITISH 或 SET DATEFORMAT DMY 运行,CAST 将无法正常工作。您应该将 convert 与样式一起使用,并且任何未显式转换的字符串文字都应采用 ISO 格式 (YYYYMMDD)。
  • 没错,我通常会这样做:cast(convert(varchar, entry_Date, 101) as datetime),但在本例中省略了它。
  • 如果 entry_date 已经是一个字符串,则转换为 101 样式的 varchar (with no length???) 不会执行任何操作。 (如果语言是英国的或日期格式是 DMT,那么该表达式仍然会失败。)为什么不只是 convert(datetime, entry_Date, 101)
  • 我一直使用该语法来省略日期中的时间戳,但我喜欢您的解决方案的简洁性,并且它应该在将来为我节省一些击键(尽管肌肉记忆)。
  • SELECT cast(convert(varchar, '08/15/2013 13:45:26.013', 101) as datetime) 产生2013-08-15 13:45:26.013 (当它不会由于语言或日期格式设置而失败时!)所以我不确定你如何以这种方式省略时间戳。还有there are much more efficient ways to trim time from date without using string functions.
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 1970-01-01
相关资源
最近更新 更多