Поиск общей «минимальной» пользовательской функции - PullRequest
0 голосов
/ 18 февраля 2010

Я создал следующую функцию, чтобы упростить фрагмент особенно сложного кода.

CREATE FUNCTION [dbo].[DSGetMinimumInt] (@First INT, @Second INT)
RETURNS INT
AS
BEGIN
  IF @First < @Second
    RETURN @First
RETURN  @Second

END

Однако он работает только для типа данных INT. Я знаю, что мог бы создать один для числовых и, возможно, для Varchar и Datetime.

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

Я гуглил это, но подошел пустой.

Ответы [ 2 ]

1 голос
/ 18 февраля 2010

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

CREATE FUNCTION [dbo].[DSGetMinimum] (@First sql_variant, @Second sql_variant)
RETURNS varchar(8000)
AS
BEGIN
    DECLARE @Value   varchar(8000)

    IF SQL_VARIANT_PROPERTY(@First,'BaseType')=SQL_VARIANT_PROPERTY(@Second,'BaseType')
        OR @First IS NULL OR @Second IS NULL
    BEGIN
        IF SQL_VARIANT_PROPERTY(@First,'BaseType')='datetime'
        BEGIN
            IF CONVERT(datetime,@First)<CONVERT(datetime,@Second)
            BEGIN
                SET @Value=CONVERT(char(23),@First,121)
            END
            ELSE
            BEGIN
                SET @Value=CONVERT(char(23),@Second,121)
            END
        END --IF datetime
        ELSE
        BEGIN
            IF @First < @Second
                SET @Value=CONVERT(varchar(8000),@First)
            ELSE
                SET @Value=CONVERT(varchar(8000),@Second)
        END

    END --IF types the same

    RETURN  @Value

END
GO

EDIT
Тестовый код:

DECLARE @D1 datetime    , @D2 datetime
DECLARE @I1 int         , @I2 int
DECLARE @V1  varchar(5) , @V2 varchar(5)
SELECT @D1='1/1/2010', @D2='1/2/2010'
      ,@I1=5        , @I2=999
      ,@V1='abc'    , @V2='xyz'
PRINT dbo.DSGetMinimumInt(@D1,@D2)
PRINT dbo.DSGetMinimumInt(@I1,@I2)
PRINT dbo.DSGetMinimumInt(@V1,@V2)

Тестовый вывод:

2010-01-01 00:00:00.000
5
abc

Если вы собираетесь использовать это в запросе, я бы просто использовал встроенный оператор CASE, который был бы НАМНОГО быстрее, чем UDF:

CASE
    WHEN @valueAnyType1<@ValueAnyType2 THEN @valueAnyType1
    ELSE @ValueAnyType2
END

при необходимости вы можете добавить защиту для NULL:

CASE
    WHEN @valueAnyType1<=ISNULL(@ValueAnyType2,@valueAnyType1) THEN @valueAnyType1
    ELSE @ValueAnyType2
END
1 голос
/ 18 февраля 2010

Все основные базы данных, кроме SQL Server, поддерживают LEAST и GREATEST, которые делают то, что вы хотите.

В SQL Server вы можете эмулировать это следующим образом:

WITH    q (col1, col2) AS
        (
        SELECT  'test1', 'test2'
        UNION ALL
        SELECT  'test3', 'test4'
        )
SELECT  (
        SELECT  MIN(col)
        FROM    (
                SELECT  col1 AS col
                UNION ALL
                SELECT  col2
                ) qa
        )
FROM    q

, хотя это будет немного менее эффективно, чем UDF.

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