Oracle案例 分页查询和分组排序

表介绍

KM_REVIEW_MAIN:流程主表

字段DOC_SUBJECT,DOC_CREATE_TIME(流程创建时间),DOC_CREATOR_ID(即SUBMITTER),FD_DEPARTMENT_ID(提交人部门),DOC_STATUS,

DOC_STATUS状态对应:

-- 10 草稿
-- 11 驳回
-- 00 废弃/提交人主动取消
-- 20 待审
-- 30 结束

IT_REQUEST_COMPLETION_DETAIL:过程记录表

每个流程状态发生变化时都会在此表记录一次,关联条件:IT_REQUEST_COMPLETION_DETAIL.FD_PROCESS_ID = KM_REVIEW_MAIN.FD_ID

记录FD_PROCESS_ID对应的FD_CREATE_TIME,FD_STATUS,FD_HANDLER_ID处理人,

每个FD_PROCESS_ID有多个不同的FD_CREATE_TIME,FD_STATUS,取最晚的FD_STATUS,就是最新状态。

正常流程:等待(或驳回)-->已受理-->完成请求-->申请人确认完毕,

要求统计为已受理、等待、问题三个状态,

状态对应:

--- 100 等待

--- 200 已受理

--- 300 申请人确认完毕

--- 404 问题

--- 600 完成请求

---其他 未知

IT_REQUEST_PLAN_TIME计划完成时间表

字段:

FD_PROCESS_ID,即KM_REVIEW_MAIN的FD_ID

FD_CREATE_TIME,本条信息创建时间

FD_PLAN_FINISH_TIME,计划完成时间

KM_REVIEW_MAIN_PROPERTY流程类型表

字段:

FD_DOC_ID,即KM_REVIEW_MAIN的FD_ID

FD_PROPERTY_ID,流程类型,

测试服务器-内部需求:16c55f20f811ce47da6b70e418192f67

测试服务器-外部需求:16c5165a9805ef77b491b074e2a8f63b

 

SYS_ORG_ELEMENT员工信息表

字段

FD_ID(唯一ID),FD_NAME(名字),FD_NO(工号)

 

SQL语句


SELECT
	T.*,
	CEIL(TOTAL_NUM / 10 ) TOTAL_PAGE
FROM(
	SELECT 
		S.*,
		COUNT(*) OVER() TOTAL_NUM,
		ROWNUM RNUM
	FROM(
		SELECT 
		M.FD_ID PROCESS_ID,
		M.DOC_SUBJECT SUBJECT,
		SOE.FD_ID SUBMITTER_ID,
		SOE.FD_NAME SUBMITTER_NAME,
		CASE P.FD_PROPERTY_ID
			WHEN '16c55f20f811ce47da6b70e418192f67' THEN '内部'
			WHEN '16c5165a9805ef77b491b074e2a8f63b' THEN '外部'
			ELSE '其他'
		END AS TYPE,
		TO_CHAR(M.DOC_CREATE_TIME,'YYYY-MM-DD') SUBMIT_TIME,
		SOE2.FD_ID DEPARTMENT_ID,
		SOE2.FD_NAME DEPARTMENT_NAME,
		SOE1.FD_ID HANDLER_ID,
		SOE1.FD_NAME HANDLER_NAME,
		TO_CHAR(PT.FD_PLAN_FINISH_TIME,'YYYY-MM-DD') PLAN_FINISH_TIME,
		D.FD_STATUS STATUS_NO,
		CASE D.FD_STATUS 
			WHEN '100' THEN '等待'
			WHEN '200' THEN '已受理'
			WHEN '404' THEN '问题'
			WHEN '600' THEN '已完成'
			WHEN '300' THEN '已完成'
			ELSE '未知状态码'
		END AS STATUS,
		D.FD_CREATE_TIME FD_CREATE_TIME,
		--依照流程ID对记录进行编号,按照时间、状态排序
		ROW_NUMBER() OVER(
			PARTITION BY D.FD_PROCESS_ID
			ORDER BY D.FD_CREATE_TIME DESC, D.FD_STATUS * 1 DESC
		) AS RN

		FROM KM_REVIEW_MAIN M
		LEFT JOIN SYS_ORG_ELEMENT SOE ON SOE.FD_ID = M.DOC_CREATOR_ID
		LEFT JOIN IT_REQUEST_COMPLETION_DETAIL D ON D.FD_PROCESS_ID = M.FD_ID
		LEFT JOIN IT_REQUEST_PLAN_TIME PT ON PT.FD_PROCESS_ID = M.FD_ID
		LEFT JOIN KM_REVIEW_MAIN_PROPERTY P ON P.FD_DOC_ID = M.FD_ID
		LEFT JOIN SYS_ORG_ELEMENT SOE1 ON SOE1.FD_ID = D.FD_HANDLER_ID
		LEFT JOIN SYS_ORG_ELEMENT SOE2 ON SOE2.FD_ID = SOE1.FD_PARENTID
		WHERE D.FD_STATUS IN ('100','200','404','600','300')
		) S
	WHERE RN = '1'
	) T
WHERE
	RNUM > 0*10 AND RNUM < 1*10
	--如果查询本周
	AND TO_DATE(SUBMIT_TIME,'YYYY-MM-DD') >= TRUNC(SYSDATE,'IW')
	AND TO_DATE(SUBMIT_TIME,'YYYY-MM-DD') < TRUNC(SYSDATE+7,'IW')
	--如果查询本月
	AND SUBSTR(SUBMIT_TIME,1,7) = TO_CHAR(SYSDATE,'YYYY-MM')
	--查询开始时间~结束时间
	AND TO_DATE(SUBMIT_TIME,'YYYY-MM-DD') >= TO_DATE('2019-08-01','YYYY-MM-DD')
	AND TO_DATE(SUBMIT_TIME,'YYYY-MM-DD') < TO_DATE('2019-08-20','YYYY-MM-DD')

	AND SUBMITTER_ID = '16437e3e2c29277f392d75c41d29574a'
	AND TYPE = '内部'
	AND DEPARTMENT_ID = '163e57e1db53402ec4897c04713a400b'
	AND STATUS = '已完成';

问题一:分组排序

KM_REVIEW_MAIN 中的一个 FD_ID,对应 IT_REQUEST_COMPLETION_DETAIL 的多条记录,

要求按照 FD_ID 分组,每组 FD_ID 的多条记录再按照时间、编号排序

分组排序方法一

左外连接查询,多层次排序,

先大排序:依照 M.FD_ID,

再小排序:依照 D.FD_CREATE_TIME DESC, D.FD_STATUS * 1 DESC

如果单纯只按 D.FD_CREATE_TIME 排序,可能出现错乱,这条流程的记录跟另一条流程的记录穿插出现,

SELECT 
    M.FD_ID PROCESS_ID,
    D.FD_STATUS STATUS_NO,
    D.FD_CREATE_TIME
FROM KM_REVIEW_MAIN M
    LEFT JOIN IT_REQUEST_COMPLETION_DETAIL D ON D.FD_PROCESS_ID = M.FD_ID
ORDER BY M.FD_ID, D.FD_CREATE_TIME DESC, D.FD_STATUS * 1 DESC

分组排序方法二

编号同时排序,编号时用 PARTITION BY 分组,用 ORDER BY 排序,

SELECT 
    M.FD_ID PROCESS_ID,
    D.FD_STATUS STATUS_NO,
    D.FD_CREATE_TIME,
    ROW_NUMBER() OVER(
        PARTITION BY D.FD_PROCESS_ID
        ORDER BY D.FD_CREATE_TIME DESC, D.FD_STATUS * 1 DESC
    ) AS RN
FROM KM_REVIEW_MAIN M
    LEFT JOIN IT_REQUEST_COMPLETION_DETAIL D ON D.FD_PROCESS_ID = M.FD_ID

问题二:取最新状态码

一个流程对应有多个流程记录,需要最后一个流程记录作为最新状态,

思路:取所有流程记录,并按时间倒序排列后编号,然后在外层查询中取编号为1的记录,

内层查询

ROW_NUMBER() OVER(
            PARTITION BY D.FD_PROCESS_ID
            ORDER BY D.FD_CREATE_TIME DESC, D.FD_STATUS * 1 DESC
        ) AS RN

外层查询筛选编号为1的

WHERE RN = '1'

问题三:分页查询

首先在内层查询语句中给每条记录编号,并查询总记录数目

    SELECT 
        S.*,
        COUNT(*) OVER() TOTAL_NUM,
        ROWNUM RNUM

假设pageSize=10,即每页展示10条记录,那么页数=TOTAL_NUM/10并向上取整,TOTAL_NUM是65,则总页数是7,

外层查询时查出总页数,并把编号进行限定在要展示的页数范围内,

SELECT
    T.*,
    CEIL(TOTAL_NUM / 10 ) TOTAL_PAGE
FROM(
    SELECT 
        S.*,
        COUNT(*) OVER() TOTAL_NUM,
        ROWNUM RNUM
        FROM (***)S
)T
WHERE
    RNUM > 0*10 AND RNUM < 1*10

问题四:查询本周数据

    AND TO_DATE(SUBMIT_TIME,'YYYY-MM-DD') >= TRUNC(SYSDATE,'IW')
    AND TO_DATE(SUBMIT_TIME,'YYYY-MM-DD') < TRUNC(SYSDATE+7,'IW')

TRUNC(SYSDATE,'IW')是查询本周一的00:00:00,注意周日属于本周最后一天,

TRUNC(SYSDATE+7,'IW')是查询下周一的00:00:00,

问题五:查询本月数据

AND SUBSTR(SUBMIT_TIME,1,7) = TO_CHAR(SYSDATE,'YYYY-MM')

问题六:同一张表的不同条件的字段放在同一行

SELECT 
    A.*,
    B1.字段1,
    B2.字段2
FROM 
    A
LEFT JOIN B AS B1 ON B1.ID = A.ID
LEFT JOIN B AS B2 ON B2.ID = A.FID

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值