3

「OMG! HE IS USING IMAGES :O :O :O」のすべての人 (元の投稿はこの下にあります):

私はテーブルを持っています:

date1 | id1 | value
date1 | id2 | value
date1 | id3 | value
date1 | id4 | value
-------------------
date2 | id1 | value
date2 | id2 | value
date2 | id5 | value
date2 | id7 | value
-------------------
date3 | id4 | value
date3 | id5 | value
date3 | id10 | value
date3 | id11 | value
-------------------
...
-------------------
dateN | id1 | value
dateN | id2 | value
dateN | id3 | value
dateN | id4 | value

次のような入力があります。

date: X - ids: 2, 3
date: Y - ids: 4
date: Z - ids: 2, 4, 5
...

すべての日付とそれ自体のすべてのID、日付の行、およびそれに固有の値を持つIDをもたらす単一のクエリ(非PL、非条件、変数またはカーソル...)が必要です。日付に特定の ID の値がない場合、その値を持つ最も近い日付を見つける必要があります。

すなわち:

date: 06/03/2016 - ids: 5, 6

結果:

06/03/2016|5|value
04/03/2016|6|value

日付が 06/03/2016 で ID=6 のレコードが見つからないため、2 番目の結果行の日付は異なります。そのため、一致する最も近い日付が表示されます。ああ、そして最も近いということは、つまり、BEFORE. 日付の後ではありません。したがって、日付が一致しない場合は、指定された同じ日またはその前の最も近い日付になります。

入力のすべての行に対してクエリを作成し、最終的にすべてから UNION を作成できます。しかし、これはそれを解決するエレガントな方法ではありません。また、PHP をオンにするたびにループでクエリをスローすることもオプションではありません。




元のスレッド:

おはようございます。スペイン出身なので、英語で失礼します。

とは言っても、最後にこの質問を簡潔にしようと思いますが、まず最初に、環境を公開させてください。

  • 典型的な日付/データ型/値のテーブルがあります。

ここに画像の説明を入力

  • 日付変更ブロックの赤い線で視覚的に分割しました。青い矢印は「データ型」ID (別のテーブルから) 列を示し、もう一方の青い矢印はそれらの値に関連付けられた日付を示します。したがって、さまざまなタイプ ID を持つ日付ブロックがあり、それぞれに変更値 (CAMBIO) があります: 緑の矢印です。

さて、私に何ができるでしょうか?特定の日付のCAMBIO値を取得するクエリ:

ここに画像の説明を入力

: GRUPO はテーブルに存在する別の列であり、常にこのグループ タイプ 1 の値が必要です。これは必須です。

次のステップは、指定された DATE のテーブル レコードに値が存在しない場合です。だから私は最も近いものを見つけなければなりません。

次のようなクエリを実行できます。

ここに画像の説明を入力

最初の画像では、3 月 6 日または 3 月 5 日のレコードがないことがわかります。したがって、このクエリを使用して、存在する最も近い値、この場合は同じ 3 月 4 日に移動できます。

これらのクエリの問題は、DIVISA_C 列を特定の値、たとえば 5 と 10 に指定する必要があることです。

ここに画像の説明を入力

これは、結果の既存の DIVISA_C ID に対して適切に機能しますが、「日付ブロック」に含まれていない ID (つまり、2016-03-04) が必要な場合は、6 としましょう。結果は得られません。この DIVISA_C id と、以前示したように、具体的には最も近い日付の結果が必要です。

私が行った場合:

ここに画像の説明を入力

この 6 ID には何もありません。最後のクエリと同じ結果。この場合、問題を解決する方法も知っています。

ここに画像の説明を入力

おわかりのように、内部クエリから自己 DIVISA_C id への WHERE に「ポインタ」を追加しました。これは基本的に、ourtsider/container クエリからの DIVISA_C を指します。これにより、内部クエリで指定された DATE に対して、コンテナ クエリの "IN リスト" 内のすべての ID に対して、期待どおりに最も可能性の高い関連行が表示されます。したがって、内部クエリが指定された DIVISA_C ID の指定された日付を解決できた場合、レコードが取得されます。それ以外の場合は、DIVISA_C id 値に最も近い日付を取得します。これはまさに私が必要としていたものです。

注:外部/コンテナー クエリと一貫性を持たせるために、内部クエリに追加のフィルターを追加しました。考慮すべき問題や変更はまったくありません。

ここで、本当の質問が来ると説明しました。

- これで、日付のリストができました。これらの日付ごとに、DIVISA_C ID のリストがあります。そして、PL-SQLを使用せずに(FOR、IF、CURSORSなどを使用せずに)単一のクエリを作成する必要があり、SELECTの組み合わせのみで、期待どおりの結果が得られます。これは基本的にこれが最後です私があなたに示した結果ですが、関連する DIVISA_C ID リストを持つ多くの日付についてです。

例として、私が示した最後のクエリは次のように説明できます。

date: 06/03/2016 - divisa_c ids: 5, 6, 10

3 月 6 日には DIVISA_C ID のレコードがないため、この場合、すべての ID の近似日付を含む 3 つの行が表示されます。

これで、1 つのクエリだけで解決する必要がある完全な入力リストができました。つまり、次のようになります。

date: 06/03/2016 - divisa_c ids: 5, 6, 10
date: 05/02/2016 - divisa_c ids: 5
date: 03/02/2016 - divisa_c ids: 5, 6
date: 01/01/2016 - divisa_c ids: 6, 10
date: 31/12/2015 - divisa_c ids: 4, 6, 10, 12
date: 24/10/2015 - divisa_c ids: 3, 4, 5, 11
...

もちろん、入力リストにある行と同じ数の PHP ループ ターンごとに 1 つのクエリを実行できます。

または、リストの入力行を使用してすべてのクエリを作成し、すべての UNION を作成して、必要な結果を正確に取得できる巨大な長い文字列クエリを作成できますが、これはオプションではありません。 もっとエレガントな方法で解決する必要がありますが、ここで立ち往生しています... :(

私は次のようなことをしました:

ここに画像の説明を入力

ご覧のとおり、外側の WHERE にある種の「リンクされた」パケットがあり、これにより、内部クエリが関連する日付ごとに DIVISA_C IN リストのすべての行を解決し、内部クエリでは DATE もポインターです...しかしご想像のとおり、内部クエリは FECHA = (サブクエリ...) を介して where にリンクされており、この後に書いたパケットが意味をなさないため、これは機能しません...

まったく同じテーブルへの外部クエリでINNER JOINを作成することを考えたので、それ自体に対するテーブルに何らかの形で2つのポインターを持ち、状況に合わせてそれらを結合します...しかし、それを適切に行う方法がわかりません.. .

これについて教えてください。

みんなありがとう、そして長い投稿でごめんなさい!でも、画像で説明した方が分かりやすいと思います。

ご挨拶、

マーク。

4

1 に答える 1

2

row_number()最も近い日の値を検索するために使用します。with節では、入力パラメーターを定義します。テスト データでは ('2016-03-04', (5)), ('2016-03-06', (5)), ('2016-03-07', ( 5、6、10))。Idは必要ありません。わかりやすくするために追加しました。

with t as ( 
  select 1 id, date '2016-03-04' fecha, 5 divisa from dual union all 
  select 2 id, date '2016-03-06' fecha, 5 divisa from dual union all 
  select 3 id, date '2016-03-07' fecha, 5 divisa from dual union all 
  select 3 id, date '2016-03-07' fecha, 6 divisa from dual union all 
  select 3 id, date '2016-03-07' fecha,10 divisa from dual )
select * from (
  select cd.*, t.fecha input_fecha, t.divisa input_divisa,
         row_number() over (partition by t.fecha, t.divisa order by t.fecha-cd.fecha) rn
    from cotizaciones_div cd 
    join t on cd.divisa_c = t.divisa and cd.grupo = 1 and cd.fecha<=t.fecha)
  where rn=1 order by input_fecha, input_divisa

入力パラメーターを定義するには、 type を使用することもできます。sys.odcinumberlistより快適な場合は、次のように ( divisaリストが長い場合は構文を短縮できます)、次のようにします。

  select 1 id, date '2016-03-04' fecha, column_value as divisa 
    from table(sys.odcinumberlist(5)) union all 
  select 2 id, date '2016-03-06' fecha, column_value as divisa 
    from table(sys.odcinumberlist(5)) union all 
  select 3 id, date '2016-03-07' fecha, column_value as divisa 
    from table(sys.odcinumberlist(5, 6, 10)) 

テストデータと出力:

create table cotizaciones_div (codigo number(8), divisa_o number(3), divisa_c number(3), 
  fecha date, cambio number(12, 4), grupo number(3));

insert into cotizaciones_div values ( 1000,  4, 11, date '2016-01-01', 0.5123, 8);
insert into cotizaciones_div values ( 2273, 15,  6, date '1998-12-31', 0,      1);
insert into cotizaciones_div values (63289,  4,  5, date '2016-03-04', 1.0998, 1);
insert into cotizaciones_div values (63297,  4, 10, date '2016-03-04', 7.4622, 1);
insert into cotizaciones_div values (63290,  4, 11, date '2016-03-04', 0.7738, 1);
insert into cotizaciones_div values (63309,  4,  5, date '2016-03-07', 1.1016, 1);
insert into cotizaciones_div values (63317,  4, 10, date '2016-03-07', 7.4619, 1);
insert into cotizaciones_div values (63310,  4, 11, date '2016-03-07', 0.7724, 1);

   CODIGO DIVISA_O DIVISA_C FECHA               CAMBIO GRUPO INPUT_FECHA INPUT_DIVISA
--------- -------- -------- ----------- -------------- ----- ----------- ------------
    63289        4        5 2016-03-04          1,0998     1 2016-03-04             5
    63289        4        5 2016-03-04          1,0998     1 2016-03-06             5
    63309        4        5 2016-03-07          1,1016     1 2016-03-07             5
     2273       15        6 1998-12-31          0,0000     1 2016-03-07             6
    63317        4       10 2016-03-07          7,4619     1 2016-03-07            10
于 2016-03-08T14:21:48.570 に答える