MySQL/Oracle查詢上一篇和下一篇sql

表結構與初始化數據如下:

--表結構
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;

結果爲:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章