【问题标题】:How to set parameters to show data from a period of time in SQL?如何在SQL中设置参数以显示一段时间内的数据?
【发布时间】:2020-08-31 14:09:34
【问题描述】:

我创建了一个 SQL 存储过程:

CREATE PROCEDURE [stored procedure name]
(
    @Location [varchar](255),
    @start_date datetime,
    @end_date datetime
)
AS
BEGIN
    SELECT id, location, name, begin_date, age, career, phone_number
    FROM information
    WHERE (begin_date = @start_date OR @start_date IS NULL) 
    AND (begin_date = @end_date OR @end_date IS NULL)
    AND (location = @Location OR @Location = 'All')
END

我的想法是将@start_date@end_date默认设置为Null,但如果用户选择这样做,它也可以显示一段时间内的特定数据,这意味着:

  1. 当我运行以下代码时:
    EXEC [stored procedure name] @start_date = NULL, @end_date = NULL, @Location = 'New York';

它将显示来自纽约的所有数据,无论时间。

  1. 当我运行以下代码时:
    EXEC [stored procedure name] @start_date = '2020-03-01', @end_date = '2020-03-31', @Location = 'New York';

它将显示 2020 年 3 月 1 日至 2020 年 3 月 31 日期间纽约的数据。 如何调整我的代码以实现这个目标?我的代码似乎缺少@start_date@end_date 之间的联系。

【问题讨论】:

  • 由于您以date 格式传递日期变量,并且您的begin_date 字段为datetime,因此在进行匹配之前可能值得转换为日期。即CONVERT(DATE,begin_date)>= @start_date
  • 尽管出于性能原因,最好where 子句中转换您的列。这就是考虑时间的范围检查更好的原因。

标签: sql sql-server tsql stored-procedures parameters


【解决方案1】:

您非常接近 - 您只需要使用大于等于 (>=) 和小于 (<) 而不是等于 (=) 进行比较。

SELECT id, location, name, begin_date, age, career, phone_number
FROM information
WHERE (begin_date >= @start_date or @start_date is null) 
And (begin_date < dateadd(day, 1, @end_date) or @end_date is null)
And (location = @Location or @Location = 'All')

注意 1:dateadd(day, 1, @end_date) 将考虑到 begin_date 的任何时间部分,因此您可以将 @end_date 设置为 31 May 2020 并包括当天的任何条目。

注意 2:除非您希望指定传入参数的时间分量,否则我将使用 date 数据类型来避免此比较发生任何意外行为。事实上,begin_date 也应该只是 date,因为我认为您通常不会跟踪某人开始的时间。

顺便说一句,如果你默认你的参数,例如

(
    @Location [varchar](255),
    @start_date datetime = null,
    @end_date datetime = null
)

您不必明确地传递它们,例如

EXEC [stored procedure name] @Location = 'New York';

【讨论】:

  • 谢谢,你的回答很详细。但是我有一个问题:begin_date &lt; dateadd(day, 1, @end_date)begin_date &lt;= @end_date是一样的吗?
  • @VivHuang 如果保证没有时间组件(您的列和参数都是日期时间),那么这两个表达式是等效的(并且您将从将数据类型更改为 date 以避免这种情况中受益问题)。如果有任何时间组件的机会,那么它们是不同的,您需要dateadd 版本。
【解决方案2】:

您在匹配确切日期时似乎错过了范围检查

    SELECT id, location, name, begin_date, age, career, phone_number
    FROM information
    WHERE (begin_date >= @start_date or @start_date is null) 
    And (begin_date <= @end_date or @end_date is null)
    And (location = @Location or @Location = 'All')

【讨论】:

  • 这与我的回答有何不同?
  • @DaleK 我开始输入时没有答案。而且我不会去阅读其他人的回答。如果它对任何人有帮助,他们就会接受。就是这样!
猜你喜欢
  • 1970-01-01
  • 2012-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
  • 1970-01-01
  • 2023-04-08
相关资源
最近更新 更多