Где предложение в столбце, которое является результатом UDF - PullRequest
4 голосов
/ 07 июля 2010

У меня есть пользовательская функция (например, myUDF(a,b)), которая возвращает целое число.

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

SELECT col1, col2, col3, 
       myUDF(col1,col2) AS X
From myTable
WHERE x>0

SQL Server пытается определить x как столбец, но это действительно псевдоним для вычисляемого значения.

Как вы можете переписать этот запрос так, чтобыфильтрация может быть выполнена по вычисленному значению без необходимости выполнения UDF более одного раза?

Ответы [ 7 ]

7 голосов
/ 07 июля 2010
With Tbl AS 
(SELECT col1, col2, col3, myUDF(col1,col2) AS X  
        From table myTable  )

SELECT * FROM Tbl WHERE X > 0
5 голосов
/ 07 июля 2010

Если вы используете SQL Server 2005 и более поздние версии, вы можете использовать Cross Apply:

Select T.col1, T.col2, FuncResult.X
From Table As T
    Cross Apply ( Select myUdf(T.col1, T.col2) As X ) As FuncResult
Where FuncResult.X > 0
4 голосов
/ 07 июля 2010

попробуйте

SELECT col1, col2, col3, dbo.myUDF(col1,col2) AS X 
From myTable 
WHERE dbo.myUDF(col1,col2) >0

, но имейте в виду, что это приведет к сканированию, поскольку это не SARGable

Вот другой способ

select * from(
SELECT col1, col2, col3, dbo.myUDF(col1,col2) AS X 
From myTable ) as  y 
WHERE x>0
2 голосов
/ 07 июля 2010

SQL Server не позволяет ссылаться на столбцы по псевдониму. Вы должны либо выписать столбец дважды:

SELECT  col1, col2, col3, myUDF(col1,col2) AS X 
From    table myTable 
WHERE   myUDF(col1,col2) > 0

Или используйте подзапрос:

SELECT  *
FROM    (
        SELECT col1, col2, col3, myUDF(col1,col2) AS X 
        From table myTable 
        ) as subq
WHERE   x > 0
1 голос
/ 07 июля 2010

В зависимости от udf и от того, насколько он полезен или часто используется, вы можете рассмотреть возможность добавления его в таблицу в виде вычисляемого столбца .После этого вы можете отфильтровать столбец как обычно и вообще не писать функции в запросах.

0 голосов
/ 07 июля 2010

На ваш вопрос лучше всего отвечают предложения «С» (CTE, я думаю, в MSSS).

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

Есть ли в таблице 10 строк и всегда 10 строк?

Постоянно ли добавляются строки?

Есть ли у вас стратегия очистки вразместить или просто позволить ему расти?

Запрос к этой таблице только один раз в месяц?

Если это «длительная» функция (даже после того, как вы ее оптимизировали),почему вы хотите выполнить это не раз, когда-либо?

Вы просили один раз, но вы действительно спрашиваете один раз за строку, за запрос.

Хранение ответа в индексе или «виртуальном столбце»

Плюсы:

Вычислить ровно один раз за строку.Время запросов не растет линейно.

Минусы: увеличивает время вставки / обновления

Расчет каждый раз

Плюсы:

Оптимизировано время вставки / обновления

Минусы: время запроса увеличивается с количеством строк.(не масштабируется)

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

Если вы не вставляете связку (зависит от вашего оборудования) строк в секунду, будет ли трата времени вперёд иметь большую разницу?

0 голосов
/ 07 июля 2010

Я не уверен на 100%, что вы делаете, но, поскольку x не является столбцом, я бы удалил его из вашего оператора SQL, чтобы вы получили:

SELECT col1, col2, col3, myUDF(col1,col2) AS X From myTable

А затем добавьте условие к своему коду, чтобы вы вызывали его только тогда, когда x > 0

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