Объединение или использование логики управления потоком, чтобы определить, по какой таблице следует составить отчет

Я работаю со сторонним приложением, где не могу изменять таблицы. Мы создали настраиваемые таблицы сопоставления «Ежемесячно» с дополнительным столбцом даты и времени «AsOfDate», где мы выгружаем данные в конце месяца и помечаем эти данные датой последнего дня месяца.

Я хочу иметь возможность создать одну хранимую процедуру (приложение предназначено для использования представления или хранимой процедуры в качестве источника всех отчетов) и использовать параметр, который будет либо использовать текущую таблицу данных (параметр может быть NULL или = сегодняшнее Дата) или используйте таблицу конца месяца и отфильтруйте по дате окончания месяца. Таким образом, у меня есть один отчет, в котором пользователь может использовать текущие данные или данные за определенный период окончания месяца.

Что бы вы предпочли (и почему) Извините, это не полностью закодировано

Решение 1. Union Query

Create Proc Balance_Report (@AsOfDate)
AS

Select Column1
From
    (Select GetDate() as AsOfDate
       , Column1 
     From Current.Balance
    Union 
    Select AsOfDate
       , Column1 From MonthEnd.Balance
    ) AS All_Balances
Where All_Balances.AsOfDate = @AsOfDate

Решение 2. Используйте оператор If для выбора таблицы

Create Proc Balance_Report (@AsOfDate)
AS

If @AsOfDate IS NULL or @AsOfDate = GetDate()
   Select GetDate() as AsOfDate
       , Column1 
     From Current.Balance
Else
    Select AsOfDate
       , Column1 From MonthEnd.Balance
    Where AsOfDate = @AsOfDate

Опять же, это не полностью закодировано и не зависит от базы данных (но это SQL Server 2005).

Редактировать: вариант решения № 2 с использованием отдельных хранимых процедур

Create Proc Balance_Report (@AsOfDate)
AS

If @AsOfDate IS NULL or @AsOfDate = GetDate()
   Exec Current_Balance_Date -- no param necessary
Else
    exec MonthEnd_Balance_Date @AsOfDate

person JeffO    schedule 07.02.2009    source источник


Ответы (2)


Как у вас все настроено, второй способ, вероятно, будет быстрее. Если бы вы использовали секционированное представление, вы могли бы настроить ограничения таким образом, чтобы оптимизированный знал, что нужно игнорировать одну или несколько таблиц в выборе, и вы получили бы ту же производительность. Это также позволит вам сохранить всю свою логику в одном операторе, а не синхронизировать два оператора. Это может быть проблемой для вас, а может и не быть, в зависимости от того, насколько сложным является оператор SELECT.

Однако следует помнить одну вещь: если вы используете второй метод, обязательно пометьте свою хранимую процедуру как WITH (RECOMPILE) (я не могу вспомнить, требуются скобки или нет - проверьте синтаксис). Таким образом оптимизатор создаст новый план запроса на основе того, какая ветвь оператора IF должна быть выполнена.

person Tom H    schedule 07.02.2009
comment
Если бы я заменил свои запросы на 2 отдельных sprocs, мне все еще нужна была бы перекомпиляция? Я ничего не имею против RECOMPILE; Мне просто было любопытно. - person JeffO; 08.02.2009
comment
Если вы использовали две отдельные хранимые процедуры, вам потребуется перекомпилировать только в том случае, если параметры повлияют на лучший план, который будет использоваться. - person Tom H; 08.02.2009

Я предпочитаю непрофсоюзное решение. Выбор из одной таблицы всегда будет быстрее, чем объединение и выбор данных одной таблицы из объединения.

person tvanfosson    schedule 07.02.2009
comment
Я думаю, что это сведется к производительности для пользователей, которые обычно смотрят на текущие данные. Я не знаю, понадобится ли мне версия этого, которая будет включать более одного периода и может включать текущий, но вопрос был не в этом. - person JeffO; 07.02.2009
comment
Добавление одного оператора If/Else никак не повлияет на вашу производительность, сравнимую с выполнением операции UNION. Используйте отдельную процедуру, если вам нужно выбрать кратные -- и да, вам нужно будет сделать там UNION. - person tvanfosson; 07.02.2009