復習 この質問 必要のない多くの作業のようです。彼らは日付で範囲を拡張しようとしています。他のデータベースでは、greatest
と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ユーザーがleast
とgreatest
の機能を模倣するクエリパターンをどのように実装するのか疑問に思っています。
GREATEST
/LEAST
GREATEST
/LEAST
GREATEST
LEAST
GREATEST
LEAST
GREATEST
LEAST
条件をCASE
ステートメントに展開しますか、またはこの機能を有効にする拡張機能、サードパーティのアドオン、またはMicrosoftからのライセンスがありますか?
一般的な方法の1つは、VALUES
句とCROSS APPLY
を使用して、2つの列を単一の列としてエイリアス化し、それぞれの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);
ただし、結果の クエリプラン は同じように見えます。
値をサブクエリにインラインで配置することもできます。このような:
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
LEAST相当:
IIF(@a < @b, @a, @b)
GREATEST相当:
IIF(@a > @b, @a, @b)
これは良いスタートです-
CASE WHEN A > B THEN A ELSE B END
ユーザー定義関数を作成します。
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
単純なケースでも機能する可能性がありますが、このアプローチにはいくつかの問題があります。
least
演算子の動作と一致しますが、Postgresとは異なります。しかし、nullに対するこの防御は、より冗長になります(nullにならないことがわかっている場合は、単純なcase when @a <= @b then @a else @b end
は機能します)。全体として、パフォーマンスが重要な場合は、case
ステートメントを長文で記述する方がよい場合があります。比較する値がいくつかある場合は、クライアント側でネストされたcase
ステートメントを生成することにも頼りました。
私は@ 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;
また、この関数はpostgresqlバージョンのように[〜#〜] null [〜#〜]を処理します。
この関数は、便宜上DBに追加できますが、組み込みのIIF
を使用するよりも10倍遅くなります。私のテストは、正確なタイプ(datetime)を持つ関数がsql_variantバージョンと同じように機能することを示しています。
PS350k値のデータセットに対していくつかのテストを実行し、パフォーマンスは同じであるようですが、sql_variantは少し高速です、しかしそれは単なるジッターだと思います。
しかし、IIFバージョンは10x倍高速です。
インラインでテストしていませんCASE WHEN
ですが、基本的にt-sqlの場合 IIFはcaseと同じです 、およびiifはオプティマイザによってcase式に変換されます。
IIFがCASEに変換されるという事実は、この関数の動作の他の側面にも影響を与えます。
結論:パフォーマンスが重要である場合はプロトタイピングのため、または[〜#〜] iif [〜#〜]を使用する方が速いコードの明快さがさらに必要で、大きな計算が含まれていない場合は、提供された関数を使用できます。