Oracle ROW_NUMBER() OVER()函數的實際場景使用

前言

最近開發的系統中有個在線諮詢功能。學生在前臺提交諮詢信息,教師能夠登陸後臺回覆諮詢。該功能設計是直接使用一張表,使用是否開始標識該條記錄是不是諮詢的開始,而後使用一個會話id標識是屬於一次諮詢,根據建立時間排序,最後就像聊天同樣。sql

後來遇到一個需求,就是須要查詢出指定教師回覆的諮詢信息的第一條問和第一條答。先查詢出全部開始的問,而後使用會話id內鏈接加子查詢。<!--more-->然而遇到的問題是教師可能有多條回答,若是直接使用mybaits返回一個list,而後再去取第一條不是不能夠。可是仍是想直接使用sql完成,通過一番查找找到:數據庫

row_number() over(partition by  col1 ORDER BY col2 ASC )

(ps:以上問題若是有更好解決辦法的歡迎評論)sass

數據庫

我將項目的數據庫表進行改造並插入數據函數

-- ----------------------------
-- Table structure for zxzx
-- ----------------------------
CREATE TABLE "ZXZX" (
"ID" VARCHAR2(64 BYTE) NOT NULL ,
"CONSULT_ID" VARCHAR2(255 BYTE) NULL ,
"CONTENT" VARCHAR2(255 BYTE) NULL ,
"CREATE_DATE" DATE NULL ,
"IS_START" VARCHAR2(255 BYTE) NULL ,
"USER_ID" VARCHAR2(64 BYTE) NULL 
)
LOGGING
NOCOMPRESS
NOCACHE
;
-- ----------------------------
-- Records of zxzx
-- ----------------------------
INSERT INTO "ZXZX" VALUES ('12sassaasd', '12123123', '第一條問', TO_DATE('2018-03-14 21:09:26', 'YYYY-MM-DD HH24:MI:SS'), '1', '111');
INSERT INTO "ZXZX" VALUES ('213123qwewq', '12123123', '第一次回答第一條問', TO_DATE('2018-03-14 22:10:16', 'YYYY-MM-DD HH24:MI:SS'), '0', '001');
INSERT INTO "ZXZX" VALUES ('sasdass2342', '12123123', '第二次回答第一條問', TO_DATE('2018-03-14 22:11:07', 'YYYY-MM-DD HH24:MI:SS'), '0', '001');
INSERT INTO "ZXZX" VALUES ('23234wewer', '12123123', '第一條問追問', TO_DATE('2018-03-14 22:22:00', 'YYYY-MM-DD HH24:MI:SS'), '0', '111');
INSERT INTO "ZXZX" VALUES ('345', '12123123', '回答一條追問', TO_DATE('2018-03-14 23:12:55', 'YYYY-MM-DD HH24:MI:SS'), '0', '001');
INSERT INTO "ZXZX" VALUES ('234324', '334455', '第二條問', TO_DATE('2018-03-14 23:08:21', 'YYYY-MM-DD HH24:MI:SS'), '1', '111');
INSERT INTO "ZXZX" VALUES ('5623365', '334455', '回答第二條問', TO_DATE('2018-03-14 23:14:07', 'YYYY-MM-DD HH24:MI:SS'), '0', '001');
INSERT INTO "ZXZX" VALUES ('12314', '112233', '問問問', TO_DATE('2018-03-14 23:14:49', 'YYYY-MM-DD HH24:MI:SS'), '1', '111');
INSERT INTO "ZXZX" VALUES ('12342', '112233', '答答答', TO_DATE('2018-03-14 23:15:15', 'YYYY-MM-DD HH24:MI:SS'), '0', '002');

-- ----------------------------
-- Indexes structure for table zxzx
-- ----------------------------

-- ----------------------------
-- Checks structure for table zxzx
-- ----------------------------
ALTER TABLE "ZXZX" ADD CHECK ("ID" IS NOT NULL);

-- ----------------------------
-- Primary Key structure for table zxzx
-- ----------------------------
ALTER TABLE "ZXZX" ADD PRIMARY KEY ("ID");

數據查詢

這裏須要將user_id=001所回答的問題查詢出,也就是上圖紅框中的信息。spa

  • 首先查詢001的回答,這裏就可能每一個會話有多條,使用前面提到的row_number() over()即可以解決重複問題:
SELECT
       row_number()  over(partition by  consult_id  ORDER BY create_date ASC ) as rn,
       id,      
       consult_id ,      
       content,      
       user_id ,      
       is_start,      
       create_date      
FROM zxzx  
WHERE user_id = '001' AND is_start !='1'

  • 接着上面的查詢,能夠看出排序分組以後的數據都有一個rn編號,接着將rn爲一取出便可:

  • 而後須要查詢出全部的問的記錄。將上面做爲子查詢,使用內鏈接並用consult_id字段鏈接。
select
   w.id,      
   w.consult_id ,      
   w.content,      
   w.user_id ,      
   w.is_start,      
   w.create_date, 
   h.id,      
   h.consult_id ,      
   h.content,      
   h.user_id ,      
   h.is_start,      
   h.create_date
from zxzx w inner join (
  select * from(
    SELECT
           row_number()  over(partition by  consult_id  ORDER BY create_date ASC ) as rn,
           id,      
           consult_id ,      
           content,      
           user_id ,      
           is_start,      
           create_date      
    FROM zxzx  
    WHERE user_id = '001' AND is_start !='1'
  )where rn = 1
) h on h.consult_id = w.consult_id 
where w.is_start = '1'
  • 最後查詢結果

知識點

數據庫結果去重

上面說到使用row_number() over()函數獲取根據某個字段分組後的一條數據,這就有點像「去重」。在Oracle中還可使用distinct來返回惟一值。設計

  1. distinct關鍵字,語法以下:
SELECT DISTINCT col FROM table_name

​ 在使用關鍵字 distinct 的時候,主要是要知道其做用於單個字段和多個字段的時候是有區別的:code

  • 做用於單個字段時,其「去重」的是表中全部該字段值重複的數據;
  • 做用於多個字段的時候,其「去重」的表中全部字段(即 distinct 具體做用的多個字段)值都相同的數據。
  1. row_number() over() 函數,語法以下:
row_number() over(partition by  col1 ORDER BY col2 ASC )

​ row_number()函數用於給記錄進行標號,over()函數的做用是將表中的記錄進行分組和排序。語法相似上面:將表中的數據按照col1進行分組,按照col2排序。partition by:表示分組。該函數主要是根據分組進行排序以後而後取出第一條數據以實現「去重」排序

鏈接查詢

  1. 內鏈接inner join on:只顯示兩張表都匹配的結果;
  2. 左外鏈接left join on:以左邊的表爲基準,顯示出左表的所有字段和右表所匹配的字段,空的用null表示;
  3. 右外鏈接right join on:與左外鏈接相反,右外鏈接會查詢出右表的全部字段,顯示左表與右表匹配的字段,空用null表示;
  4. 全鏈接full join on:顯示兩張表所有內容。
相關文章
相關標籤/搜索