T-SQL — получение даты по динамическим параметрам

#sql-server #sql-server-2005 #tsql

#sql-сервер #sql-server-2005 #tsql

Вопрос:

Я попытался вычислить динамический запрос, чтобы получить указатель даты в течение последних 20 дней. Идея довольно проста, и, более того, я знаю, что таблица содержит даты от getdate() до -20 дней, но результат по-прежнему не возвращается

 DECLARE @date_past_period varchar(MAX);
DECLARE @date_past_number varchar(MAX);
SET @date_past_period='day';
SET @date_past_number='20';

DECLARE @aDate datetime;

DECLARE @sql varchar(MAX);
SET @sql='SELECT date FROM table WHERE convert(varchar,date,121) BETWEEN convert(varchar,getdate(),121) AND convert(varchar,dateadd(' @date_past_period ', -' @date_past_number ', getdate()),121)';


exec(@sql);
  

Возможно, проблема в динамической вещи, но я не уверен.

Приветствуется любой полезный комментарий

Комментарии:

1. не уверен, почему вы не используете хранимую процедуру и обход exec .

2. Это тестовый фрагмент. И столбец даты базы данных содержит сохраненные значения в формате «02 Oct 2008 11:02: 07: 577 » входящие параметры ожидаются в другом формате, например «гггг-мм-дд чч: мм: сс.ммм», поэтому я попытался создать общий формат таким образом. Конечно, я не уверен, что это оптимальный способ, поэтому, если вы можете посоветовать лучший, сделайте это, пожалуйста 🙂

3. Могу ли я предложить добавить несколько переменных? Вызовите GETDATE() только один раз, затем вычислите начальную и конечную даты с этой даты / времени. Используйте их в запросе для проверки столбца [дата] без преобразования его в строку. Таким образом, оптимизатор может использовать индекс (gasp) для эффективного поиска нужных строк.

Ответ №1:

Вы можете использовать CASE функцию (T-SQL):

 CREATE PROCEDURE MyStoredProcedure 
@IntervalType VARCHAR(15),
@Num INT
AS

DECLARE @StartDate DATETIME = GETDATE();
DECLARE @EndDate DATETIME = 
    CASE @IntervalType
        WHEN 'DAY' THEN DATEADD(DAY,@Num,@StartDate)
        WHEN 'MONTH' THEN DATEADD(MONTH,@Num,@StartDate)
        WHEN 'YEAR' THEN DATEADD(YEAR,@Num,@StartDate)
    END;

IF @EndDate IS NULL
    RAISERROR('Invalid params', 16, 1);
ELSE
    SELECT date FROM table WHERE date BETWEEN @StartDate AND @EndDate;
  

При преобразовании в VARCHAR ваше условие поиска из WHERE не будет SARG (1 и 2).

Комментарии:

1. 1 На мой взгляд, это лучший ответ, потому что он защищает от sql-инъекций, тогда как другой ответ — нет.

Ответ №2:

Я почти уверен, что этот сценарий может быть рассмотрен без использования динамического SQL, однако одной из очевидных проблем в вашем SQL является предложение between — диапазон находится в неправильном порядке. Попробуйте изменить свой @sql, как показано ниже:

 SET @sql='SELECT date FROM table WHERE convert(varchar,date,121) BETWEEN convert(varchar,dateadd(' @date_past_period ', -' @date_past_number ', getdate()),121) AND convert(varchar,getdate(),121)';
  

Комментарии:

1. Нет, это не может быть нединамичным, потому что параметры, такие как день / неделя / месяц и т.д. в функции dateadd, в любом случае должны быть переменными 🙂 Или, может быть, есть лучший способ сделать это?

2. О, здорово! Проблема с заказом была 🙂 Сейчас это сработало, но я все еще думаю об оптимизации. Нормально ли, что я пытался таким образом привести все к общему формату даты?

3. @user592704: если ваш ответ решен, рассмотрите возможность проверки его как принятого.