掘金 后端 ( ) • 2024-05-05 17:13

image.png

没错,又是京华的开发老哥,这次找我问个SQL实现逻辑的案例。

我博客的案例基本都是他给我的,真的是又要帮他优化SQL还要教他实现SQL逻辑

开发老哥写的SQL:

SELECT ROW_NUMBER() OVER (ORDER BY X.OBJ_CODE ASC) AS row_number,X.*
FROM (
 SELECT OBJ_CODE,OBJ_NAME,LEVEL
 FROM XFWQ_SOURCE.INNO_DEPLOY_12315_OBJECT_V1
 START WITH OBJ_PARENT_CODE = '10000000'
 CONNECT BY PRIOR OBJ_CODE = OBJ_PARENT_CODE
) X
WHERE X.LEVEL IN (1,2)
ORDER BY X.OBJ_CODE ASC

image.png

其实这条SQL很简单,主题部分是个递归查询,CONNECT BY PRIOR OBJ_CODE = OBJ_PARENT_CODE 从父节点到往子节点开始向下遍历,level 展现层级关系。

开发老哥想实现的是这种效果,例如一个Level=1的,加上行号1,第二个Level=1,加上行号2,每个LEVEL = 1 层级的数字顺序往下递归。

image.png

这种需求在MySQL的代码实现会比较简单,可以使用个临时变量(@i:=@i+1),每次加1 即可, 但是在DM数据库上需要变换一种实现思路

下面为了让读者更好理解如何实现这段逻辑的思路,笔者将分段需求拆开改写:

1、首先主体SQL(递归查询)先取出 LEVEL 层级为 (1,2)的节点

SELECT OBJ_CODE,
       OBJ_NAME,
       LEVEL
FROM (
SELECT OBJ_CODE, OBJ_NAME, LEVEL
      FROM XFWQ_SOURCE.INNO_DEPLOY_12315_OBJECT_V1
      START WITH OBJ_PARENT_CODE = '10000000'
      CONNECT BY PRIOR OBJ_CODE = OBJ_PARENT_CODE) X
      WHERE X.LEVEL IN (1, 2);

image.png

2、然后对主体SQL进行 row_number() over() 开窗,对 LEVEL 进行分组,OBJ_CODE 进行排序,就可以得出 LEVEL = 1 的顺序 rownum 。

SELECT OBJ_CODE,
       OBJ_NAME,
       LEVEL,
       row_number() over(partition by level order by OBJ_CODE) rn
FROM (

SELECT OBJ_CODE, OBJ_NAME, LEVEL
      FROM XFWQ_SOURCE.INNO_DEPLOY_12315_OBJECT_V1
      START WITH OBJ_PARENT_CODE = '10000000'
      CONNECT BY PRIOR OBJ_CODE = OBJ_PARENT_CODE
      
      ) X
WHERE X.LEVEL IN (1, 2);

image.png

可以看到,LEVEL = 1 的所有数据已经按顺序排好序,也是递增的数字。

3、最后一步就简单了,大家估计已经猜到了怎么做,没错,就是case when 。

LEVEL = 1 的都拼接上 OBJ_NAME。


SELECT OBJ_CODE,
         (case when level = 1 then rn||'、'||OBJ_NAME else OBJ_NAME end ) OBJ_NAME,
       level
 from (
SELECT OBJ_CODE,
       OBJ_NAME,
       LEVEL,
       row_number() over(partition by level order by OBJ_CODE) rn
FROM (SELECT OBJ_CODE, OBJ_NAME, LEVEL
      FROM XFWQ_SOURCE.INNO_DEPLOY_12315_OBJECT_V1
      START WITH OBJ_PARENT_CODE = '10000000'
      CONNECT BY PRIOR OBJ_CODE = OBJ_PARENT_CODE) X
WHERE X.LEVEL IN (1, 2)
) ORDER BY 1,2;

image.png

image.png

到这里,这条SQL逻辑已经完成,开发老哥的需求也能完美实现。

总结:

1、其实这条SQL开发老哥都写得差不多能实现这个逻辑,就是其中一段没琢磨清楚。**

2、无论是优化SQL,还是复杂SQL的实现,包括现实中很多是工作需求,都可以用  "拆" 字诀,

3、把大需求拆成小需求,分段实现,然后串联到一起,这样能解决绝大部分的需求和问题。