2011-11-14 29 views
6

OracleとMySQLでは、GREATEST(value1、value2、...)のように呼び出すことができるように、無数のパラメータをとる関数を作成するにはどうすればよいですか?SQLユーザー定義関数の引数の数は不定ですか?

2つの値を特定の標準と比較するのはかなり簡単ですが、もう1つの比較に「より大きい」値を渡すと、SQLで動作しないように見えます。

ありがとうございます!

編集(下記のMikeのコメントの後): 複数の列を比較するソリューションを探しています。具体的には、私の質問は、UREFとしてGREATEST()を実装する方法です。次のコードは、3つの列を比較します。

SELECT CASE WHEN CASE WHEN col_1 < col_2 THEN col_2 
       ELSE col_1 END < col_3 THEN col_3 
     ELSE CASE WHEN col_1 < col_2 THEN col_2 
       ELSE col_1 END END AS greatest 
    FROM figures; 

明らかに、これはうまくスケールされません。同じ比較メソッドを値のリストに繰り返し適用する一般的な関数を持つ方がずっと便利です。 SQLによって

私は、任意のSQLデータベース製品を意味するが、私は、Oracleで動作またはOracle(アンピボットをサポートするインスタンス)でのMySQL

+0

は、これは同じです* from、x desc/ascの順 最大値は最初/最後でなければなりませんか? XSLTでも、最大値を得るためにソートするだけですか? – Mike

+0

おそらくあなたはSQL Serverを意味しています - それ以上の資格を持たないSQLは言語を指し、様々な製品によって様々な程度に実装され、それぞれ独自の固有の拡張もあります。 –

+2

これは、 'case'ステートメントのスケーラビリティを向上させる方法の1つです。 http://stackoverflow.com/questions/7995945/how-to-i-modify-this-t-sql-query-to-return-the-maximum-value-for-different-colum/7996068#7996068 –

答えて

2

SELECT MyID, MAX(GreatestVal) 
FROM figures 
    UNPIVOT (
      GreatestVal 
      FOR MyID 
      IN (col_1, col_2, col_3,...) 
     ); 

Oracleのクエリが原因でテストされていないソリューションを好みます unpivotの詳細はlocated hereで、SQL Serverのunpivotと同じことをしています。 (。誰かが私を打つ場合を除き;-))

MySQLの 私は、MySQLでこれを行う方法がわからないんだけど、私は機会を持つよう検討すること

次のSQL Serverの答えです:

すべての場合にすべての入力パラメータが必須であるため、UDFで行うのはきれいではありません。ストアドプロシージャとして実装することができれば、入力パラメータのデフォルト値を指定し、動的な列数で呼び出すことができます。いずれにしても、入力パラメータの最大数を決める必要があります。ここではSQL Server上のUDFの例です:

SELECT dbo.GREATESTof3(col_1, col_2, col_3) 
FROM figures; 

CREATE FUNCTION GREATESTof3(@col_1 sql_variant = null, @col_2 sql_variant = null, @col_3 sql_variant = null) 
RETURNS sql_variant 
AS 
BEGIN 
    DECLARE @GreatestVal sql_variant 
    DECLARE @ColumnVals TABLE (Candidate sql_variant) 


    INSERT INTO @ColumnVals 
    SELECT @col_1 
    UNION ALL 
    SELECT @col_2 
    UNION ALL 
    SELECT @col_3 

    SELECT @GreatestVal = MAX(Candidate) 
    FROM @ColumnVals 

    RETURN @GreatestVal 
END 

これは、入力パラメータの数の各バリアントのための新しいUDFを必要以上の数を取ることができるものを作成が、その後UDFあなたへの呼び出しになり未使用の各パラメータ(null)にいくつかの値を指定するか、デフォルトを指定する必要があります。

代替:

これはあなたの全体のテーブルから3つのカラムの最大値を与えると列の動的な数を持つことが容易になるだろう:

SELECT MAX([Value]) AS Greatest 
FROM figures 
UNPIVOT 
(
    [Value] 
    FOR ColumnName IN ([Col_1], [Col_2], [Col_3]) 
) AS unpvt 

はあなたには、いくつかのROWIDを持っていると仮定すると、または出力に必要な別の列を指定して、各行の指定された列から最大の値を得ることができます。

SELECT RowID, MAX([Value]) AS Greatest 
FROM figures 
UNPIVOT 
(
    [Value] 
    FOR ColumnName IN ([Col_1], [Col_2], [Col_3]) 
) AS unpvt 
GROUP BY RowID 
0

別のSQL Serverオプション(MySQL/Oracleへの変換方法が不明)。私はカンマ区切りのリストに入れ、最大取得する機能に供給する前にその整数IDのリストでこれを行うために持っていた

: - 選択

CREATE Function [dbo].[GreatestFromList] 
(@ListOfValues VARCHAR(8000)) 

RETURNS INT 

AS 

BEGIN 

DECLARE @ListOfValuesTable TABLE (ValueColumn INT) 

    DECLARE @spot1 SMALLINT, @str1 VARCHAR(8000) 

    WHILE @ListOfValues <> '' 
    BEGIN 
     SET @spot1 = CHARINDEX(',', @ListOfValues) 
     IF @spot1>0 
      BEGIN 
       SET @str1 = LEFT(@ListOfValues, @spot1-1) 
       SET @ListOfValues = RIGHT(@ListOfValues, LEN(@ListOfValues)[email protected]) 
      END 
     ELSE 
      BEGIN 
       SET @str1 = @ListOfValues 
       SET @ListOfValues = '' 
      END 
     INSERT INTO @ListOfValuesTable (ValueColumn) VALUES(convert(int, @str1)) 
    END 

DECLARE @GreatestValue INT 

SELECT @GreatestValue = SELECT MAX(ValueColumn) FROM @ListOfValuesTable 

RETURN @GreatestValue 

END 
関連する問題