2013-07-04 37 views
1

比方說,我有這個表使用「排序依據」和工會內部獲取在SQL上AS400數據庫

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語句。當我將它與union結合使用時,select語句內部不允許使用和獲取函數(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) 

任何人都可以請告訴我什麼是錯的,它應該如何?此外,請分享,如果你知道其他方式來實現我想要的結果。

+1

如果40或者你正在尋找的任何號碼碰巧在你的桌子上,你會得到什麼結果? – WarrenT

+1

是否有可能有相同數量的行?然後怎樣呢? – WarrenT

+0

@WarrenT:其他程序確保該值不會等於金額。但是,謝謝你。這讓我想到了未來可能出現的問題。對於第二個問題,只要我可以得到越來越小的數額,重複金額就可以了。謝謝!! – ides

回答

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))) 
+0

是的,巴克。當時沒有一個盒子可以測試,相當不錯。 ;-) – WarrenT

+0

CTE =公用表表達式? – ides

+0

我不斷收到此錯誤「Keyword FROM not expected。Validkens:),。」。順便說一句,你缺少封裝您的ID =(選擇一個括號...語句。 – ides

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 

一個這種方法的優點是性能。如果您正在查找多個值的範圍(例如表或查詢中的列),那麼使用範圍視圖應該會顯着提高性能,而不是查詢必須彙總大於或小於每個搜索值的所有記錄的查詢。

1

這是我的查詢使用CTE和聯盟靈感來自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 

這有點慢,但我可以接受,因爲我只會在程序中使用它一次。

這只是一個例子。實際的查詢有點不同。