SQL ServerはGREATESTとLEASTをサポートしていますか?サポートされていない場合、一般的な回避策は何ですか?


15

この質問を検討するとそれは必要のない多くの作業のようです。彼らは日付で範囲を拡大しようとしています。他のデータベースでは、単にgreatestandを使用しleastます。

least(extendDate,min), greatest(extendDate,max)

これらを使用しようとすると、

'least' is not a recognized built-in function name.
'greatest' is not a recognized built-in function name.

それはどちらの方向への拡張もカバーします。

質問の目的のために、あなたはまだ排他的な範囲置換をしなければならないでしょう。

SQL Serverユーザーがどのようにクエリパターンを実装して模倣するかleastgreatest機能するのか疑問に思っています。

条件をCASEステートメントに展開しますか、またはこの機能を有効にする拡張機能、サードパーティのアドオン、またはマイクロソフトからのライセンスがありますか?


MSSQLにLEAST/のGREATEST機能が実装されていないことは驚くべきことです。ほぼすべてのRDBMS競合他社には少なくとも同等のものがあります。私が見つけた唯一の例外はSybaseですが、それはこの時点で長年にわたって廃止されました。
bsplosion

回答:


32

一般的な方法の1つは、VALUES句を使用しCROSS APPLY、2つの列を1つの列としてエイリアス化してから、MINおよびMAX、それぞれをです。

SELECT MIN(x.CombinedDate) AS least, MAX(x.CombinedDate) AS greatest
FROM   dbo.Users AS u
CROSS APPLY ( VALUES ( u.CreationDate ), ( u.LastAccessDate )) AS x ( CombinedDate );

それを書く他の方法があります。例えば、 UNION ALL

SELECT MIN(x.CombinedDate) AS least, MAX(x.CombinedDate) AS greatest
FROM   dbo.Users AS u
CROSS APPLY ( SELECT u.CreationDate UNION ALL SELECT u.LastAccessDate ) AS x(CombinedDate);

ただし、結果のクエリプランは同じように見えます


12

また、値をインラインでサブクエリに入れることもできます。このような:

select (select max(i) from (values (1), (2), (5), (1), (6)) AS T(i)) greatest,
       (select min(i) from (values (1), (2), (5), (1), (6)) AS T(i)) least

3

これは良いスタートになるでしょう-

CASE WHEN A > B THEN A ELSE B END

それは良い提案ですが、「条件をCASEステートメントに展開する」という質問で言及されました
エヴァンキャロル

3

同等以上:

IIF(@a < @b, @a, @b)

同等の最大:

IIF(@a > @b, @a, @b)

3
たとえば、3つ以上の値に対してこれを行うにはどうしますleast(5,6,7,8,9)か?
a_horse_with_no_name

@a_horse_with_no_name使用はIIFのネストされた
Elnur

このアプローチは、すぐに読み取りと検証が困難になります...パフォーマンスの点でどのように機能しますか?
ドデカフォン

0

たとえば、ユーザー定義関数を作成します

create function dbo.udf_LeastInt(@a int, @b int)
returns int
with schemabinding
as
begin
  return case when @a <= @b then @a 
              when @b < @a  then @b
              else null
         end
end

単純なケースでは機能する場合もありますが、このアプローチにはいくつかの問題があります。

  • 面倒なことに、データ型ごとに別々の関数を作成する必要があります。
  • 2つのパラメーターのみを処理するため、多くのパラメーターを処理したり、同じ関数のネストされた呼び出しを使用したりするには、より多くの関数が必要になる場合があります。
  • スカラー関数よりもインラインTVFの方が優れています(より効率的)。それは、中心のスカラー関数の実装に関係しています。これについては多くのブログがあります。たとえば、SQL 101:Parallelism Inhibitors – Scalar User Defined Functions(by John Kehayias)を参照してください
  • 引数の1つがnullの場合、nullを返します。これは、leastオペレーターがOracleおよびMySQLで行うことと一致しますが、Postgresとは異なります。しかし、nullに対するこの装甲により、より冗長になります(nullにならないことがわかっている場合は、プレーンcase when @a <= @b then @a else @b endが機能します)。

case全体として、パフォーマンスが重要な場合は、ステートメントを手書きで記述する方が良い場合があります。case比較する値がいくつかある場合、クライアント側でネストされたステートメントを生成することにさえ頼りました。


0

@ ed-avisの回答にコメントを追加するつもりでしたが、評判が足りないため追加できませんでした。そのため、これを彼の回答の拡張として投稿しました。

「面倒なことに、データ型ごとに別々の関数を作成しなければならない」という欠点を取り除きました。SQL_VARIANTを使用します

これが私の実装です。

CREATE OR ALTER FUNCTION my_least(@a SQL_VARIANT, @b SQL_VARIANT)
returns SQL_VARIANT
with schemabinding
as
begin
  return case when @a <= @b then @a 
              when @b < @a  then @b
              WHEN @a IS NULL THEN @b
              WHEN @b IS NULL THEN @a
              else null
         end
END;

また、この関数はNULLを処理します postgresqlバージョンのように。

この関数は便宜上DBに追加できますが、組み込みを使用するよりも10倍遅くなりますIIF。私のテストでは、そのような正確な型(datetime)の関数はsql_variantバージョンと同じように動作することが示されています。

PS 350kの値のデータセットでいくつかのテストを実行し、パフォーマンスは同じように見えますが、sql_variantは少し速いですが、それは単なるジッタだと思います。

しかし、とにかくIIFバージョンは10倍高速です!!!

私はインラインでテストしていませんCASE WHENが、基本的にt-sql IIFの場合はcaseと同じで、iif getはオプティマイザーによってcase式に変換されます。

IIFがCASEに変換されるという事実は、この関数の動作の他の側面にも影響を与えます。

結論:パフォーマンスが重要な場合はIIFを使用する方が高速ですが、プロトタイプを作成する場合、またはコードを明確にする必要があり、大きな計算が必要ない場合は、関数を使用できます。


1
「sqlvariantはほんの少し高速です」と言い、「IIFバージョンは10倍高速です」と言います。何より速い?
ypercubeᵀᴹ

SQLバリアントバージョンは、別の回答で提供されているように、具体的なバージョンとほぼ同じ速度です。私のテストでは、80ミリ秒(15秒から)でしたが、統計エラーだけだと思います。またiif(a<b, a, b) 、ユーザー定義関数の10倍の速度で使用できます。
ボグダンマート

明確にするために、sql_variantをdatetimeに置き換えたコードを2番目の関数として使用しました。テストの後は、sql_variant型は、任意のオーバーヘッドを追加しないと思われますが、ユーザー定義関数は、より、道遅いビルトイン
ボグダンマート

しかし、これらの関数のいずれかはIIF()CASE式を使用するよりも高速ですか?私のポイントは、パフォーマンステストの問題に直面したので、提案されたすべての方法/回答をテストする必要があるということです。
ypercubeᵀᴹ

1
@yper-crazyhat-c​​ubeᵀᴹが回答を更新しました。それ以上は編集せず、単にsql_variantに関するコメントをed-avisの回答に追加したかったのですが、パイントが不足しているため、拡張回答を書く必要がありました:-)
ボグダンマート
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.