Обединяване или използване на логиката за управление на потока, за да определите за коя таблица да докладвате

Работя с трето приложение, където не мога да променя таблиците. Създадохме персонализирани съвпадащи таблици „Месечни“ с допълнителна колона за дата и час „AsOfDate“, където изхвърляме данните в края на месеца и маркираме тези данни с датата на последния ден от месеца.

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

Кое бихте предпочели (и защо) Съжаляваме, това не е напълно кодирано

Решение №1 Обединена заявка

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

Отново, това не е напълно кодирано и е нещо като db агностик (но е 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