2017-01-03 153 views
0

我有一個表foos(id,fieldA,fieldB,fieldC ...)。我有一個SQL查詢返回了我一些行集選擇行間隔,包括某些行與where和order子句

SELECT * from foos WHERE whereClauseN ORDER BY orderClauseM 

的現在,從這個集合,我需要選擇5列ID X:

  1. 如果ID爲X的行是該組的前5行必須返回該組的前5行。
  2. 如果id爲X的行在集合的最後5行中,則必須返回該集合的最後5行。
  3. 如果具有id X的行不在前5行而不在最後5行中,則必須返回行X前2行和行X後2行的行。

如何使這樣的SQL查詢(我需要H2和PostgreSql)?

對於執行上述的SQL代碼後例如,如果我已經下面的一組(爲簡單起見僅FIELDA示出):

| id | fieldA | 
_______________ 
| 5 | aaaaa | 
| 7 | bbbbb | 
| 23 | tttttt | 
| 22 | ssssss | 
| 12 | rrrrrr | 
| 96 | eeeeee | 
| 48 | qqqqqq | 
| 3 | wwwwww | 
_______________ 

的對於情況1,其中X = 7以下一組必須返回:

| id | fieldA | 
_______________ 
| 5 | aaaaa | 
| 7 | bbbbb | 
| 23 | tttttt | 
| 22 | ssssss | 
| 12 | rrrrrr | 
_______________ 

的用於殼體2,其中X = 96下面的一組必須返回:

| id | fieldA | 
_______________ 
| 22 | ssssss | 
| 12 | rrrrrr | 
| 96 | eeeeee | 
| 48 | qqqqqq | 
| 3 | wwwwww | 
_______________ 

的用於殼體3,其中X = 12下面的一組必須返回:

| id | fieldA | 
_______________ 
| 23 | tttttt | 
| 22 | ssssss | 
| 12 | rrrrrr | 
| 96 | eeeeee | 
| 48 | qqqqqq | 
_______________ 
+0

請將您的問題標記爲您正在使用的數據庫。 –

+0

@Gordon Linoff我編輯了問題 –

+1

**您的問題並添加一些樣本數據和基於該數據的預期輸出。 [**格式化文本**](http://stackoverflow.com/help/formatting)請,[無屏幕截圖](http://meta.stackoverflow.com/questions/285551/why-may-i-not上傳問題時的代碼問題/ 285557#285557) –

回答

1

假設一個行已ID X,那麼我會傾向於使用窗函數來枚舉的行,並獲得用於該行數「X」值:

with t as (
     select f.*, 
      row_number() over (orderClauseM) as seqnum, 
      count(*) over() as numrows 
     from foo t 
     where . . . 
     order by orderClauseM 
    ) 
select . . . 
from (select t.*, 
      max(case when id = X then seqnum end) over() as seqnum_X 
     from t 
    ) t 
where (seqnum_X <= 5 and seqnum <= 5) or 
     (seqnum_X >= cnt - 5 and seqnum >= cnt - 5) or 
     seqnum between seqnum_X - 2 and seqnum_X + 2; 
+0

'cnt'是什麼? –

+0

如果對你來說不難,請解釋這行'max(id = X,然後seqnum結束時)over()as seqnum_X' –

+0

@PavelKasotov。 。 。 'cnt'是表中行的總數('seqnum'的最大值)。 'max()'表達式將所有行上的'X'的'seqnum'值「擴散」。 –