1

我正在构建一个动态查询作为 SQL Server 2008 中的存储过程,当我比较日期(作为参数提供)和日期时间(存储在数据库中)时,我得到了一些意想不到的结果。我四处寻找一些方法来比较两者而不考虑时间部分,结果发现:

DATEDIFF(day, @d, v.ScheduledDate) = 0

我正在做的是试图找到提供的日期参数和存储的 ScheduledDate 相同的记录(以天为单位,例如 02/05/2011 和02/05/2011 11:26:19.157)。这是我为此编写的查询:

SET @sql = 'SELECT e.Id, e.FirstName, e.LastName, v.ScheduledDate
            FROM Employee e, Visit v
            WHERE 1=1'
-- Several IF IS NOT NULL statements here

IF @d IS NOT NULL
BEGIN
  SET @sql = @sql + ' AND DATEDIFF(day, ''' + @d + ''',' + 'v.ScheduledDate) = 0
  AND v.EmpId = e.Id '
END
EXEC (@sql)

我希望此查询会为任何安排在当天访问的员工生成所有 ScheduledDates。换句话说,如果我有两个 ID 为 5 和 7 的员工,并且在 Visit 表中存在两个 ScheduleDate 条目,分别是 02/05/2011 的 ID 为 5 和 7 的员工,我希望这两个员工都回来时我运行此查询。然而,似乎当我运行它时,我只能得到一排。(作为旁注,我正在使用的两个 ScheduledDate 条目在同一天,但彼此相隔大约 3 小时。我认为 DATEDIFF 函数可以解释这一点,因为几个小时肯定在一天的时间范围。)如果我将查询中的 = 更改为 >= 0 或 <= 0,我会按预期获得更多行,但奇怪的是仍然只能获得该特定日期的单个条目。表中还有其他记录,其中同一员工在不同日期有多次访问,当我使用 >= 0 或 <= 0 时,相应地返回这些记录。例如,ID 为 41 的员工在 2011 年 10 月 29 日有 3 次访问, 11-24-2011 和 12-28-2011 当我将 DATEDIFF 更改为 >= 0 时,所有 3 个都将返回。我仍然很困惑为什么我只在两个不同的员工时才取回单个记录安排在同一日期访问。谁能提供一些关于我的逻辑在哪里出错的见解?请注意,当我对此进行测试时,我只提供了 ScheduledDate 参数。所有其他 IF IS NOT NULL 语句都会失败,因为所有其他参数都作为 NULL 插入。并且当我使用 >= 0 或 <= 0 时相应返回。例如,ID 为 41 的员工在 2011 年 10 月 29 日、2011 年 11 月 24 日和 2011 年 12 月 28 日有 3 次访问以及所有 3 次访问当我将 DATEDIFF 更改为 >= 0 时返回。我仍然很困惑为什么当两个不同的员工在同一日期安排访问时我只取回单个记录。谁能提供一些关于我的逻辑在哪里出错的见解?请注意,当我对此进行测试时,我只提供了 ScheduledDate 参数。所有其他 IF IS NOT NULL 语句都会失败,因为所有其他参数都作为 NULL 插入。并且当我使用 >= 0 或 <= 0 时相应返回。例如,ID 为 41 的员工在 2011 年 10 月 29 日、2011 年 11 月 24 日和 2011 年 12 月 28 日有 3 次访问以及所有 3 次访问当我将 DATEDIFF 更改为 >= 0 时返回。我仍然很困惑为什么当两个不同的员工在同一日期安排访问时我只取回单个记录。谁能提供一些关于我的逻辑在哪里出错的见解?请注意,当我对此进行测试时,我只提供了 ScheduledDate 参数。所有其他 IF IS NOT NULL 语句都会失败,因为所有其他参数都作为 NULL 插入。我仍然对为什么我只在两个不同的员工在同一日期安排访问时才取回单条记录感到困惑。谁能提供一些关于我的逻辑在哪里出错的见解?请注意,当我对此进行测试时,我只提供了 ScheduledDate 参数。所有其他 IF IS NOT NULL 语句都会失败,因为所有其他参数都作为 NULL 插入。我仍然对为什么我只在两个不同的员工在同一日期安排访问时才取回单条记录感到困惑。谁能提供一些关于我的逻辑在哪里出错的见解?请注意,当我对此进行测试时,我只提供了 ScheduledDate 参数。所有其他 IF IS NOT NULL 语句都会失败,因为所有其他参数都作为 NULL 插入。

4

4 回答 4

1

这是深入的,但信息量很大:http: //www.sommarskog.se/dyn-search.html

SET @sql = N'SELECT e.Id, e.FirstName, e.LastName, v.ScheduledDate
             FROM Employee e, Visit v
             WHERE v.EmpId = e.Id'

-- Several IF IS NOT NULL statements here
IF @d IS NOT NULL
  SET @sql = @sql + N' AND (v.ScheduledDate >= @date AND v.ScheduledDate < @date + 1)'

-- This stays the same, EVEN if the parameter is NULL and not used
-- This ensures execution plan re-use is available
SET @param_definition = '@date DATETIME,    -- Or whatever type v.ScheduledDate is
                         @smeg INT,
                         @head WHATEVER'

SP_EXECUTESQL
    @sql,
    @param_definition,
    @date = CAST(@d AS DATE),
    @smeg = 0,
    @head = NULL
于 2011-12-23T16:32:49.597 回答
0

我认为最好的做法是删除日期的时间部分,像这样

DECLARE @dt DATETIME
SELECT @dt = GETDATE()
SELECT CAST(FLOOR(CAST(@dt AS FLOAT)) AS DATETIME)

那么您可以使用普通的旧 = 进行比较

于 2011-12-23T16:07:54.117 回答
0

我今天刚刚做了同样的事情(使用那行代码进行动态查询)。这是我的代码行:

DATEDIFF(day,SchDate,GetDate()) = 0

它工作得很好。抱歉,我无法为您提供更多帮助,但我读了 4 次,在 datediff 部分找不到任何错误。我做了和你一样的事情,而且效果很好。但是,如果你愿意,你可以使用类似的东西:

(AND day(@d) = day (v.ScheduledDate)) AND (month(@d) = month(v.ScheduledDate)) AND (year(@d) = year(v.ScheduledDate))

也许这会起作用(我只是用随机日期对其进行了测试,并且确实如此)。Ofc 您需要添加 +@d+ 和其他内容,因为动态查询没有 @d 变量,但您已经知道 =-)

希望这可以帮助!

于 2011-12-23T16:30:37.063 回答
0

这可能是遥不可及的,但我从你到目前为止所描述的一切(包括你对 Dems 答案的评论)中的最佳猜测是Employee和之间的关系Visit不是单独由 定义的v.EmpId = e.Id,而是一个复合键,你错过了它的一部分在你的加入/在哪里条件。类似的东西v.EmpId = e.Id AND v.CompanyID = e.CompanyID

于 2011-12-23T17:12:03.853 回答