1

このテーブルがあるとしましょう

Table name: Traffic
Seq.     Type     Amount
1        in       10
2        out      30
3        in       50
4        out      70

私が必要とするのは、前の小さい値と次に大きい値を取得することです。したがって、値として 40 がある場合、次のようになります...

Table name: Traffic
Seq.     Type     Amount
2        out      30
3        in       50

私はすでにMYSQLでそれを試してみましたが、結果には非常に満足しています

(select * from Traffic where
Amount < 40 order by Amount desc limit 1)
union
(select * from Traffic where
Amount > 40 order by Amount desc limit 1)

問題は、AS400 で受け入れられる SQL ステートメントに変換しようとしたときに発生します。order by と fetch 関数 (AS400 には limit 関数がないため、fetch を使用しますか?) は、select ステートメント内でユニオンと共に使用すると許可されないようです。予期しないキーワードのエラーが常に発生します。これが私の声明です。

(select seq as sequence, type as status, amount as price from Traffic where
Amount < 40 order by price asc fetch first 1 rows only)
union
(select seq as sequence, type as status, amount as price  from Traffic where
Amount > 40 order by price asc fetch first 1 rows only)

何が間違っていて、どうあるべきか教えてください。また、私の望ましい結果を達成するための他の方法を知っている場合は、共有してください.

4

3 に答える 3

2

私はおそらく別の観点からこの質問を見ました。行間の日時範囲に関する他の質問を見たことがありますが、おそらくあなたがしようとしているのは、値がどの範囲に収まるかを確立することだと思いました.

これらの範囲で作業することが繰り返しテーマになる場合は、そのためのビューを作成することをお勧めします。

create or replace view traffic_ranges as
  with sorted as
  ( select t.*
         , smallint(row_number() over (order by amount)) as pos
     from traffic t
  )
  select b.pos    range_seq
       , b.id     beg_id
       , e.id     end_id
       , b.typ    beg_type
       , e.typ    end_type
       , b.amount beg_amt
       , e.amount end_amt
    from sorted b
    join sorted e  on e.pos = b.pos+1
;

このビューを取得すると、答えを得るのが非常に簡単になります。

select * 
  from traffic_ranges
  where 40 is between beg_amt and end_amt

または、検索金額がたまたまベース テーブルの金額である 1 つの範囲のみを取得するには、範囲の一部として開始値または終了値を含めるかどうかを選択し、もう一方を除外する必要があります。

  where beg_amt < 40 and end_amt >= 40

このアプローチの利点の 1 つはパフォーマンスです。テーブルやクエリの列など、複数の値の範囲を見つける場合、範囲ビューを使用すると、各検索値よりも多いまたは少ないすべてのレコードを集計する必要があるクエリよりもパフォーマンスが大幅に向上します。 .

于 2013-07-04T17:42:03.960 に答える