Динамический внутренний запрос - PullRequest
1 голос
/ 02 марта 2012

Есть ли способ кодировать динамический внутренний запрос?По сути, я снова и снова набираю что-то вроде следующего запроса:

;with tempData as (
   --this inner query is the part that changes, but there's always a timeGMT column.
   select timeGMT, dataCol2, dataCol3
   from tbl1 t1
      join tbl2 t2 on t1.ID=t2.ID
)
select dateadd(ss,d.gmtOffset,t.timeGMT) timeLocal,
   t.*
from tempData t
   join dst d on t.timeGMT between d.sTimeGMT and d.eTimeGMT
where d.zone = 'US-Eastern'

Единственное, о чем я могу думать - это сохраненный процесс с внутренним текстом запроса в качестве входных данных для некоторого динамического sql ...Однако мое понимание оптимизатора (которое, по общему признанию, ограничено) говорит, что это не очень хорошая идея.

Ответы [ 2 ]

1 голос
/ 02 марта 2012

С точки зрения производительности, у вас есть версия, на которой оптимизатор будет работать лучше всего.

Если «внешняя» часть вашего примера является статической, а обслуживание кода переопределяет производительность, я хотел бы инкапсулировать результат dateadd в табличную функцию (TVF). Поскольку преобразование времени является очень распространенным потоком в этих запросах, я бы определенно сосредоточился на этой части рабочей нагрузки.

Например, ваш запрос, который может отличаться, будет выглядеть так:

select timeGMT, dataCol2, dataCol3, lt.timeLocal
from   tbl1 t1
       join tbl2 t2 on t1.ID = t2.ID
       cross apply dbo.LocalTimeGet(timeGMT, 'US-Eastern') AS lt

Где TVF dbo.LocalTimeGet содержит логику для dateadd (ss, d.gmtOffset, t.timeGMT) и поиск значения смещения часового пояса на основе имени часового пояса. Реализация этой функции будет выглядеть примерно так:

CREATE FUNCTION dbo.LocalTimeGet (
    @TimeGMT  datetime,
    @TimeZone varchar(20)
)
RETURNS TABLE
AS
RETURN (
    SELECT  DATEADD(ss, d.gmtOffset, @TimeGMT) AS timeLocal
    FROM    dst AS d
    WHERE   d.zone = @TimeZone
);
GO

Достоинством этого подхода является то, что при обновлении до 2008 или более поздней версии есть системные функции, которые вы могли бы использовать, чтобы сделать это преобразование намного проще для кодирования, и вам нужно будет только изменить TVF. Если ваши наборы результатов невелики, я бы рассмотрел системную скалярную функцию (SQL 2008) поверх TVF, даже если она реализует те же системные функции. Исходя из вашего комментария, похоже, что системные функции не будут делать то, что вам нужно, но вы все равно можете придерживаться своей реализации таблицы dst, которая инкапсулирована в TVF выше.

TVF могут вызывать проблемы с производительностью, поскольку оптимизатор предполагает, что они возвращают только 1 строку.

Если вам нужно объединить инкапсуляцию и производительность, я бы вместо этого вычислил часовой пояс в коде приложения. Несмотря на то, что вам придется применять его к каждому проекту, который его использует, вам нужно будет только реализовать его 1 раз в каждом проекте (на уровне доступа к данным) и рассматривать его как общую служебную библиотеку, если вы будете использовать ее в разных проектах. .

0 голосов
/ 02 марта 2012

Чтобы ответить на дополнительный вопрос OP, решение SQL Server 2008 будет выглядеть следующим образом:

Сначала создайте постоянные определения:

CREATE TYPE dbo.tempDataType AS TABLE (
    timeGMT DATETIME,
    dataCol2 int,
    dataCol3 int)
GO

CREATE PROCEDURE ComputeDateWithDST
    @tempData tempDataType READONLY
AS
SELECT dateadd(ss,d.gmtOffset,t.timeGMT) timeLocal, t.*
FROM @tempData t
JOIN dst d ON t.timeGMT BETWEEN d.sTimeGMT AND d.eTimeGMT
WHERE d.zone = 'US-Eastern'
GO

Впоследствии, когда вы захотите подключитьподзапрос (который теперь стал отдельным запросом, уже не CTE) в хранимую процедуру:

DECLARE @tempData tempDataType

INSERT @tempData
-- sample subquery:
SELECT timeGMT, dataCol2, dataCol3
FROM tbl1 t1
JOIN tbl2 t2 ON t1.ID=t2.ID

EXEC ComputeDateWithDST @tempData;
GO

Производительность может быть проблемой, потому что вы будете запускать отдельно то, что раньше было CTE вместопозволяя SQL Server объединить его с основным запросом для оптимизации плана выполнения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...