最近开发的系统中有个在线咨询功能。学生在前台提交咨询信息,教师能够登陆后台回复咨询。该功能设计是直接使用一张表,使用是否开始标识该条记录是不是咨询的开始,而后使用一个会话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
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'
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
来返回惟一值。设计
SELECT DISTINCT col FROM table_name
在使用关键字 distinct 的时候,主要是要知道其做用于单个字段和多个字段的时候是有区别的:code
row_number() over(partition by col1 ORDER BY col2 ASC )
row_number()函数用于给记录进行标号,over()函数的做用是将表中的记录进行分组和排序。语法相似上面:将表中的数据按照col1进行分组,按照col2排序。partition by:表示分组。该函数主要是根据分组进行排序以后而后取出第一条数据以实现“去重”排序
inner join on
:只显示两张表都匹配的结果;left join on
:以左边的表为基准,显示出左表的所有字段和右表所匹配的字段,空的用null
表示;right join on
:与左外链接相反,右外链接会查询出右表的全部字段,显示左表与右表匹配的字段,空用null
表示;full join on
:显示两张表所有内容。