表結構與初始化數據如下:
--表結構
create table T_NEWS
(
ID NUMBER not null
constraint T_NEWS_PK
primary key,
TITLE VARCHAR2(300),
TURN NUMBER
)
/
comment on column T_NEWS.TITLE is '標題'
/
comment on column T_NEWS.TURN is '排序字段'
/
-- 初始化數據
INSERT INTO SCOTT.T_NEWS (ID, TITLE, TURN) VALUES (11, '烈士紀念日向人民英雄敬獻花籃儀式', 1);
INSERT INTO SCOTT.T_NEWS (ID, TITLE, TURN) VALUES (22, '慶祝新中國成立70週年大會和閱兵式將隆重舉行', 2);
INSERT INTO SCOTT.T_NEWS (ID, TITLE, TURN) VALUES (33, '中國女排11連勝奪冠 郎平笑着笑着就哭了', 3);
INSERT INTO SCOTT.T_NEWS (ID, TITLE, TURN) VALUES (44, '獲頒勳章後 袁隆平:第二天又要到田裏去', 4);
我們這裏的上一篇和下一篇的排序是根據turn字段來排序獲取的,並且turn唯一,可以通過業務代碼來保證.
一.MySQL
-- 上一篇
select ID, TITLE, TURN from T_NEWS where TURN < 2 order by id desc limit 1
--下一篇
select ID, TITLE, TURN from T_NEWS where TURN > 2 order by id limit 1
二.Oracle
oracle有兩種方式,
第一種方式是使用類似MySQL的方式,用分頁的方式解決,oracle沒有像MySQL的limit函數,所以只能用rownum來實現;
第二種方式是用oracle內置的lead和lag函數來解決.
方式一:分頁方式
-- 上一篇
select * from (select tmp.*,rownum r2 from
(select id, title, turn, rownum r1 from T_NEWS where TURN < 4 order by TURN desc) tmp
where rownum <=1)
where r2 >0;
如我們這裏查找的是turn爲4的上一篇,很明顯結果應該爲turn爲3的那條數據.
結果如下:
-- 下一篇
select * from (select tmp.*,rownum r2 from
(select id, title, turn, rownum r1 from T_NEWS where TURN > 1 order by TURN asc ) tmp
where rownum <=1)
where r2 >0;
如我們這裏查找的是turn爲1的下一篇,很明顯結果應該爲turn爲2的那條數據.
結果如下:
方式二:使用oracle內置的函數
--查詢上一篇
select * from T_NEWS where id =
(select tmp.pre_id from
(select id,lag(id,1,null) over (order by turn) as pre_id from T_NEWS) tmp
where tmp.id =33);
如我們這裏查找的是id=33的上一篇,很明顯結果應該爲id爲22的那條數據.
結果如下:
--查詢下一篇
select * from T_NEWS where id =
(select tmp.next_id from
(select id,lead(id,1,0) over (order by turn) as next_id from T_NEWS) tmp
where tmp.id =33);
如我們這裏查找的是id=33的下一篇,很明顯結果應該爲id爲44的那條數據.
結果如下:
三.lead和lag函數詳解
lag與lead函數是跟偏移量相關的兩個分析函數,通過這兩個函數可以在一次查詢中取出同一字段的前N行的數據(lag)和後N行的數據(lead)作爲獨立的列,從而更方便地進行進行數據過濾。這種操作可以代替表的自聯接,並且LAG和LEAD有更高的效率。
over()表示 lag()與lead()操作的數據都在over()的範圍內,他裏面可以使用partition by 語句(用於分組) order by 語句(用於排序)。partition by a order by b表示以a字段進行分組,再 以b字段進行排序,對數據進行查詢。
例如:
lead(field, num, defaultvalue) field需要查找的字段,num往後查找的num行的數據,defaultvalue沒有符合條件的默認值。
如下sql,用來查詢每條數據的上一條數據的id:
select id,lead(id,1,null) over (order by turn) as pre_id from T_NEWS;
結果爲: