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 语句时。当我将它与联合一起使用时,在 select 语句中似乎不允许 order by 和 fetch 功能(AS400 没有限制功能,所以我们使用 fetch,或者是吗?)。我总是得到一个关键字不是预期的错误。这是我的声明;

(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

CTE怎么样?从内存(没有机器可以测试):

with 
  less as (select * from traffic where amount < 40),
  more as (select * from traffic where amount > 40)
select * from traffic
  where id = (select id from less where amount = (select max(amount from less))) 
     or id = (select id from more where amount = (select min(amount from more))) 
于 2013-07-04T15:03:36.227 回答
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

或者要仅获取一个范围,其中搜索量恰好是基表中的一个量,您需要选择是否将开始值或结束值作为范围的一部分,并排除另一个:

  where beg_amt < 40 and end_amt >= 40

这种方法的一个优点是性能。如果您要查找多个值的范围,例如表或查询中的列,那么与必须聚合大于或小于每个搜索值的所有记录的查询相比,使用范围视图应该会给您带来更好的性能.

于 2013-07-04T17:42:03.960 回答
1

这是我使用 CTE 和 union 的查询,灵感来自 Buck Calabro 的回答。归功于他和 WarrenT 是 SQL 天才!

我不会接受我自己的答案。那将是不公平的。呵呵

 with 
apple(seq, type, amount) as (select seq, type, amount from traffic where amount < 40 
order by amount desc fetch first 1 rows only),
banana(seq, type, amount) as (select seq, type, amount from traffic where
amount > 40 fetch first 1 rows only)
 select * from apple
union
 select * from banana

这有点慢,但我可以接受,因为我只会在程序中使用它一次。

这只是一个示例。实际的查询有点不同。

于 2013-07-08T02:39:40.540 回答