#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: если ваш ответ решен, рассмотрите возможность проверки его как принятого.