DATEADD和BETWEEN无法正常工作

时间:2012-03-23 10:01:42

标签: sql sql-server sql-server-2008 tsql sql-server-2005

我有以下代码:

DECLARE @testDate date
--SET @testDate=dateadd(wk, 5830, 0)
SET @testDate='2011-09-26 00:00:00.000'

SELECT *
FROM dbo.timesheets
WHERE @testDate BETWEEN convert(datetime, start_dtm, 120) and convert(datetime, end_dtm, 120)

PRINT @testDate

它应该将值5830转换回日期格式,然后在start_dtmend_dtm之间进行检查

我通过在上面的代码中对数据库中的值进行硬编码来测试这个,但我仍然没有看到任何记录。打印的@testdate显示如下:2011-09-26

我正在创建一个week_ref我正在通过查询字符串传递。然后,时间表报告会将week_ref例如'5830'转换为日期,并检查其是否在start_dtmend_dtm之间。从理论上讲,它应该显示结果,以检查值是否在开始和结束之间。

有什么想法吗?还是帮忙调试?

编辑:时间表中的行:

Example row from timesheets table

以下是我正在努力解决的问题:

DECLARE @week_ref INT
DECLARE @weekDate date

set @weekDate=dateadd(wk,@week_ref,0)



SELECT     ts.staff_member_ref, sm.common_name, sm.department_name, DATENAME(MONTH, ts.start_dtm) + ' ' + DATENAME(YEAR, ts.start_dtm) AS month_name, 
                      ts.timesheet_cat_ref, cat.desc_long AS timesheet_cat_desc, grps.grouping_ref, grps.description AS grouping_desc, ts.task_ref, tsks.task_code, 
                      tsks.description AS task_desc, ts.site_ref, sits.description AS site_desc, ts.site_ref AS Expr1, 
                      CASE WHEN ts .status = 0 THEN 'Pending' WHEN ts .status = 1 THEN 'Booked' WHEN ts .status = 2 THEN 'Approved' ELSE 'Invalid Status' END AS site_status, 
                      ts.booked_time AS booked_time_sum,

start_dtm, CONVERT(varchar(20), start_dtm, 108) + ' ' + CONVERT(varchar(20), start_dtm, 103) AS start_dtm_text, booked_time,
end_dtm, CONVERT(varchar(20), end_dtm, 108) + ' ' + CONVERT(varchar(20), end_dtm, 103) AS end_dtm_text


FROM timesheets AS ts 

INNER JOIN timesheet_categories AS cat ON ts.timesheet_cat_ref = cat.timesheet_cat_ref 
INNER JOIN timesheet_tasks AS tsks ON ts.task_ref = tsks.task_ref 
INNER JOIN timesheet_task_groupings AS grps ON tsks.grouping_ref = grps.grouping_ref 
INNER JOIN timesheet_sites AS sits ON ts.site_ref = sits.site_ref 
INNER JOIN vw_staff_members AS sm ON ts.staff_member_ref = sm.staff_member_ref
--INNER JOIN week_list AS WL ON ts.timesheet_ref = WL.week_ref

--WHERE (ts.status IN (1, 2)) AND (cat.is_leave_category = 0)
--AND WL.week_ref=@week_ref AND WL.start_week BETWEEN ts.start_dtm AND ts.end_dtm

WHERE @weekDate <= convert(datetime, end_dtm, 120) 
AND @weekDate > convert(datetime, start_dtm, 120)



GROUP BY ts.staff_member_ref, sm.common_name, sm.department_name, DATENAME(MONTH, ts.start_dtm), DATENAME(YEAR, ts.start_dtm), ts.timesheet_cat_ref, 
                      cat.desc_long, grps.grouping_ref, grps.description, ts.status, ts.booked_time, ts.task_ref, tsks.task_code, tsks.description, ts.site_ref, sits.description, ts.start_dtm, 
                      ts.end_dtm
ORDER BY sm.common_name, timesheet_cat_desc, tsks.task_code, site_desc

3 个答案:

答案 0 :(得分:2)

我想要你考虑2个查询:

declare @timesheets table(start_dtm datetime, end_dtm datetime)

insert @timesheets values('2011-09-26', '2011-09-27')
insert @timesheets values('2011-09-28', '2011-09-29')


-- This will return 1 row
SELECT *
FROM @timesheets
WHERE dateadd(wk, 5830, 0) BETWEEN start_dtm and end_dtm

-- This will return both rows
SELECT *
FROM @timesheets
WHERE 5830 BETWEEN datediff(wk, 0, start_dtm) and datediff(wk, 0, end_dtm)

如果不是必要的话,你应该避免转换/转换。

答案 1 :(得分:2)

我认为你真的想要:

DECLARE @testDate date
SET @testDate=dateadd(wk, 5804, 0)
--SET @testDate='2011-03-28 00:00:00.000'

SELECT *
FROM dbo.timesheets
WHERE @testDate <= convert(datetime, end_dtm, 120) and 
      dateadd(wk, 1, @testDate) > convert(datetime, start_dtm, 120)

PRINT @testDate

此版本的查询会测试记录日期范围的任何部分是否在@testDate开始的一周内。

答案 2 :(得分:1)

基于编辑,这应该可以正常工作:

DECLARE @testDate datetime
SET @testDate='2011-09-26 00:00:00.000'

SELECT *
FROM dbo.timesheets
WHERE @testDate BETWEEN start_dtm and end_dtm 

或者你可能有这个问题(没有时间信息,你只有一天:

     SELECT *
     FROM dbo.timesheets
     WHERE @testDate BETWEEN start_dtm and end_dtm 
  OR @testDate = start_dtm OR @testDate = end_dtm

有些变量是日期类型,有些是日期时间。我会这样做

DECLARE @testDate date
SET @testDate='2011-09-26 00:00:00.000'

SELECT *
FROM dbo.timesheets
WHERE @testDate BETWEEN cast(start_dtm as date) and cast(end_dtm as date)

DECLARE @testDate datetime
SET @testDate='2011-09-26 00:00:00.000'

SELECT *
FROM dbo.timesheets
WHERE @testDate BETWEEN cast(start_dtm as datetime) and cast(end_dtm as datetime)