0

CASE WHEN 構造を使用する Transact SQL ステートメントを書き直して、CASE WHEN を使用せずに同じことを行う方法はありますか?

組み込みのクエリ デザイナーと独自の疑似 SQL を備えた製品を使用しています。SQL Server と Oracle で使用できるものには制限があります。したがって、基になるデータベースが Oracle の場合、DECODE (サポートされている) を使用するこの列があります。ただし、SQL Server で動作させる必要があり、CASE WHEN はサポートされていません。

変換しようとしているステートメントは次のようなものです

Decode (StatusColumn,  'Value 1',
Decode(Sign(Now()-TargetDateColumn)),1,'Past
Due', 'Outstanding'),  'Value 2',
Decode(Sign(Now()-TargetDateColumn)),1,'Past
Due', 'Outstanding'),  'Value 3',
Decode(Sign(Now()-TargetDateColumn)),1,'Past
Due', 'Outstanding'),  'Value 4')

使用する T-SQL オプションのセットは限られていますが、CASE WHEN はオプションではありません。私は IsNull と Coalesce を持っていますが、これが役立つかどうかはわかりません。

日付の計算を気にしないでください。それらは解決されています。

ここでCASE WHENの質問を検索しましたが、役に立ちませんでした。

ありがとう!

アップデート:

これは開発者向けのリソースであり、これは開発製品であると想定されるため、制限の理由について詳しく説明する必要があったことを認識しています。そうではない。

組み込みのクエリ デザイナーと独自の疑似 SQL を備えたエンタープライズ ソフトウェア製品を使用しています。SQL Server と Oracle で使用できるものには制限があります。基本的に、組み込みのクエリ エンジンの解析を妨げないものはすべてゲームです。これは、承認されたすべての関数と式、およびすべてのデータ抽象化 (データベース内の物理テーブルに対応する内部オブジェクトおよび製品で作成されたその他のクエリ)、および解析を明示的に中断しない Oracle SQL または Transact SQL からのすべてを意味します。 .

CASE WHEN が機能しない理由は、クエリ エンジンによる疑似 SQL の解析が中断されるためです。

最終的には、次のことを試してみたいと思います。

  1. 製品のクエリ デザイナーのみを使用して、解析 OR を渡す SQL
  2. これを行うには、SQL Server データベースとクエリ デザイナーからいくつかの追加リソースを使用します。

私が得たいくつかの良い答えに基づいて、これまでのところ私にとってうまくいったアプローチは次のとおりです。

Jason DeFontes は、データベース ビューを使用して CASE WHEN ルールを実行できると提案しましたが、これは上記の #2 に該当します。ビューは動的であるため、メンテナンスを行う必要がないため、私にとってはうまくいきます(ジェイソンのアプローチに近いと思われるrichartallentの真理値表アプローチとは対照的です)。関数を作成するという Pascal の提案は同じ方向に進みますが、おそらく解析を中断します。

そこで、CASE WHEN を使用してすべての変換を行うデータベース ビューを作成し、それをクエリの SQL に追加して、既存の SQL と結合したところ、問題なく動作しました。同じデータ セットを 2 回 (ビュー用とクエリ用に 1 つずつ) 取得する必要があるため、おそらくデータベース エンジンにオーバーヘッドが追加されていることを認識していますが、これはほとんど問題にならないケースの 1 つです。

この「ビューを使用して難読化する」設計が機能することを考えると、より効率的なアプローチは何でしょうか。

  • CASE WHEN での選択の使用。
  • CTE の使用 (繰り返しますが、richardtallent);
  • Union All (HLGEM) の使用;
  • サブクエリの使用 (MisterZimbu);

おそらく上記の#1に該当する可能性があるため、Aramis wylerの提案を引き続き確認します。

今のところ、ジェイソンの答えは受け入れられました。ビューで CASE WHEN を使用したことを考えると、質問のタイトルが不適切に選択された可能性があります。私は、プロセスに役立つ何かを提案したすべての人を元気づけました. それがあなたの評判に影響を与えるかどうかはわかりませんが、それは良いことだと思いました.

繰り返しになりますが、皆さんのご協力に感謝いたします。また、質問の不適切な部分を編集していただけるようお願いいたします (これは私の最初の質問であり、英語は私の第二言語です)。

4

6 に答える 6

4

ユニオンはすべて利用できますか?おそらく、where句のcaseの条件を使用して各条件のクエリを記述し、それらを結合することができます。

于 2009-11-05T18:20:25.740 に答える
3

カスタム サブクエリを作成できますか? CASE WHEN にアクセスできない場合はおそらくそうではありませんが、これもおそらく機能します。

select
    ...,
    coalesce(c1.value, c2.value, c3.value, ..., <default value>)
from MyTable
left join (select <result 1> as value) c1 on <first condition>
left join (select <result 2> as value) c2 on <second condition>
left join (select <result 3> as value) c3 on <third condition>
于 2009-11-05T19:04:27.330 に答える
1

あなたのコードを理解しているかどうかは正確にはわかりませんが、これにより別のアプローチのアイデアが得られるはずです。

まず、テーブルを作成します。

CREATE TABLE StatusLookup(
   value nvarchar(255),
   datesign shortint,
   result varchar(255));

ここで、真理値表を入力します (ここには多くのロジックが繰り返されているようです。おそらく、これは間に CROSS JOIN がある 2 つの真理値表である必要があります)。

INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', -1, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', 0, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 1', 1, 'Past Due')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', -1, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', 0, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 2', 1, 'Past Due')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', -1, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', 0, 'Outstanding')
INSERT INTO StatusLookup(value, datesign, result) VALUES ('Value 3', 1, 'Past Due')

最後に、参加してデフォルトの回答を提供します。

SELECT mytable.*, COALESCE(statuslookup.result, 'Value 4')
FROM
    mytable LEFT JOIN statuslookup ON
        statuslookup.value = StatusColumn
        AND statuslookup.datesign = Sign(Now()-TargetDateColumn)

このアプローチの重要な利点の 1 つは、ビジネス ロジックをコードではなくデータ テーブルに配置できることです。これにより、多くの場合、保守と拡張が容易になります。

于 2009-11-05T19:30:33.993 に答える
1

CASE WHEN を使用して計算を実行する関数を作成します。

于 2009-11-05T18:10:05.147 に答える
1

It's ugly and depending on the number of values you have it may not be viable. But strictly speaking, I think something like this would work as a translation from the above query segment:

select 'PastDue' from tablename where Now() > TargetDateColumn and (StatusColumn = 'Value 1' or StatusColumn = 'Value 2' or StatusColumn = 'Value 3') union select 'Outstanding' where Now() < TargetDateColumn and (StatusColumn = 'Value 1' or StatusColumn = 'Value 2' or StatusColumn = 'Value 3') union select 'Value 4' where NOT (StatusColumn = 'Value 1' or StatusColumn = 'Value 2' or StatusColumn = 'Value 3')

于 2009-11-05T19:07:13.953 に答える