Пакетная обработка SQL-запросов (входной массив SQL-запросов) - PullRequest
1 голос
/ 23 августа 2011

У меня SQL-запрос вроде

SELECT *, dbo.func(@param1, a.point) as fValue 
FROM dbo.table AS a 
WHERE dbo.func(@param1, a.point) < @param2

Когда этот запрос выполняется только один раз, все в порядке, но когда у меня есть массив значений input @ param1, скажем, более 100 значений, выполнение и выборка результатов для каждого значения занимает много времени.

Можно ли каким-либо образом передать массив запроса @ param1 в запрос и получить набор данных для всех входных значений вместо выполнения его для каждого значения?

Функция func () выполняет математические вычисления для 2 значений. @ param1 и a.point являются типом double. и, да, точка. - это не идентификатор, и это не уникальное значение.

Я знаю, это должно быть действительно легко, но похоже, что я что-то упустил.

Ответы [ 3 ]

1 голос
/ 23 августа 2011

Вам все еще нужно выполнить эту функцию 100 раз для каждой строки, верно?Я не вижу здесь никаких ярлыков.

Если бы вы хотели получить их все сразу, вы могли бы сделать

SELECT dbo.func(@param1, a.point) as fValue1, 
       dbo.func(@param2, a.point) as fValue2 ...

или что-то в этом роде, но циклический просмотр их просто кажется более эффективнымв любом случае мне.

Полагаю, вы могли бы использовать курсор для получения каждого значения a.point один раз, а затем воздействовать на него 100 раз, но это много кода, и не обязательно более простое решение.

0 голосов
/ 23 августа 2011

Есть ли у вас индексы в этой таблице? Если у вас есть индекс для a.point, вы никогда не поразите его, используя этот код, то есть всегда будете сканировать таблицу. Это связано с поисковыми аргументами (вы можете гуглить это). Пример:

Если у вас есть таблица xTable с индексом для столбца xColumn, то это:

select colA, colB from xTable where xColumn/2 >= 5

будет никогда использовать индекс, но это, вероятно, будет:

select colA, colB from xTable where xColumn >=10

Так что вам может понадобиться что-то вроде этого:

WHERE a.point < Otherfunc(@param1,  @param2 )
0 голосов
/ 23 августа 2011

Что именно делает dbo.func()?Возможно ли, что вы могли бы вставить 100 значений в структуру таблицы и выполнить эту операцию на множестве 100 одновременно, а не 1x1 100 раз?

В качестве примера, скажем, у вас есть эта функция, который просто превращает разделенный запятыми список значений с плавающей точкой в ​​таблицу с одним столбцом:

CREATE FUNCTION dbo.ListFloats
(
    @List VARCHAR(MAX)
)
RETURNS TABLE
RETURN
(
    SELECT i = CONVERT(FLOAT, Item)
    FROM
    (
        SELECT Item = x.i.value('(./text())[1]', 'FLOAT')
        FROM
        (
            SELECT [XML] = CONVERT(XML, '<i>'
                + REPLACE(@List, ',', '</i><i>')
                + '</i>').query('.')
        ) AS a
        CROSS APPLY
        [XML].nodes('i') AS x(i)
    ) AS y
    WHERE Item IS NOT NULL
);
GO

Теперь вы должны иметь возможность получить свои числа с плавающей точкой, просто сказав:

SELECT i FROM dbo.ListFloats('1.5, 3.0, 2.45, 1.9');

Если сделать еще один шаг вперед, скажем, dbo.func() берет эти два входа и говорит что-то вроде:

RETURN (SELECT (@param1 + @param2 / @param2));

Теперь я знаю, что вам всегда говорили, что модульность и инкапсуляция хороши,но в случае встроенных функций я бы посоветовал вам избегать функции, которая получает этот результат (опять же, вы не объяснили, что делает dbo.func(), поэтому я просто предполагаю, что это будет легко), и сделайте это встроенным.Поэтому вместо вызова dbo.func() - дважды для каждой строки, не менее - вы можете просто сказать:

DECLARE 
    @Param1Array VARCHAR(MAX) = '1.5, 3.0, 2.45, 1.9',
    @Param2 FLOAT = 2.0;

WITH x AS 
(
    SELECT t.point, x.i, fValue = ((x.i + t.point)/t.point) 
    FROM dbo.[table] AS t
    CROSS JOIN dbo.ListFloats(@Param1Array) AS x
)
SELECT point, i, fValue FROM x
--WHERE fValue < @Param2
;

Ключи:

  1. Избегание обработки каждого параметраиндивидуально.

  2. Избегание отдельных расчетов в отдельном модуле.

  3. Выполнение расчетов как можно меньше раз.

Если вы не можете так сильно изменить структуру, то, по крайней мере, не рассчитывайте функцию дважды, написав вместо этого:

;WITH x AS 
(
    SELECT *, dbo.func(@param1, a.point) as fValue 
    FROM dbo.table AS a 
)
SELECT * FROM x 
    WHERE fValue < @param2;

Если вы предоставите подробную информацию о типах данных, что делает dbo.func() и т. д., люди смогут дать более осязаемый совет.

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