My Life My Dream!

守信 求实 好学 力行
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

通用表表达式(CTE,COMMON TABLE EXPRESSION)

通用表表达式(CTE)是标准的SQL语法,本质上是临时命名的结果集。CTE最初于1999年出现在SQL标准(即所谓的SQL-99标准),然而第一个实现好像是在出现在2007年的SQL Server 2008

SQL通常在面向过程的递归结构方面支持较弱,CTE允许查询引用自身。递归CTE将重复执行数据的子集,直到获得完整的结果集。这对于处理分层或树状数据特别有用。

 

目前主流数据库平台都已支持CTE语法,只是在数据类型和函数等细节方面存在细微差异,影响不大。国产的达梦数据库从7.0开始也支持了CTE语法,点赞!

按照SQL标准写,就是舒服,建议使用符合标准SQL,而非方言。

 

SQL Server


-- 递归所有下级
WITH --RECURSIVE
cte1 AS (
     SELECT g.*
         , cast (g.name_chs as varchar(1000)) as full_name
         , (ROW_NUMBER() over(order by g.sortorder)) * POWER(10, 5) as order_num
         , 5 as levelId
     from gspfunc g
     where g.id = 'HIP'
     UNION ALL
     SELECT g.*
         , cast(cte1.full_name + '-' + g.name_chs as varchar(1000)) as full_name
         , order_num  + (ROW_NUMBER() over(order by g.sortorder) * POWER(10, levelid-1)) as order_num
         , levelid - 1 as levelid
     FROM cte1 join gspfunc g
         ON g.parentid = cte1.id
)
SELECT id, code, name_chs, full_name, path, order_num, levelid , *
FROM cte1
order by cte1.order_num;



-- 递归找上级
WITH --RECURSIVE
  cte1 AS (
     SELECT g.*, cast (g.name_chs as varchar(1000)) as full_name
     FROM gspfunc g
     WHERE g.code = 'service-status-monitor'
     UNION ALL
     SELECT g.*, cast(cte1.full_name + '-' + g.name_chs as varchar(1000)) as full_name
     FROM cte1 join gspfunc g
         ON g.id = cte1.parentid
  )
SELECT id, code, name_chs, full_name , path, *
FROM cte1
ORDER BY cte1.full_name;

 

Oracle、DM

WITH --RECURSIVE
cte1(id, code, name_chs, parentid, full_name) AS (
     SELECT g.id, g.CODE , g.NAME_CHS , g.PARENTID
         , cast (g.name_chs as varchar(1000)) as full_name
      from gspfunc g
     where g.id = 'HIP'
     UNION ALL
      SELECT g.id, g.CODE, g.NAME_CHS , g.PARENTID
         , cast(cte1.full_name || '-' || g.name_chs as varchar(1000)) as full_name
       FROM cte1 join gspfunc g
           ON g.parentid = cte1.id
   )
   SELECT id, code, name_chs, PARENTID , full_name
   FROM cte1
   ORDER BY cte1.full_name;

 

MySQL

WITH RECURSIVE  cte1 AS (
     SELECT g.id, g.CODE , g.NAME_CHS , g.PARENTID
         , cast(g.name_chs as char(1000)) as full_name
     from gspfunc g
     where g.id = 'HIP'
     UNION ALL
     SELECT g.id, g.CODE, g.NAME_CHS , g.PARENTID
         , CONCAT(cte1.full_name , '-' , g.name_chs)  as full_name
     FROM cte1 join gspfunc g
          ON g.parentid = cte1.id
  )
  SELECT id, code, name_chs, PARENTID, full_name
  FROM cte1
  ORDER BY cte1.full_name;

 

PostgreSQL

WITH RECURSIVE  cte1 AS (
     SELECT g.id, g.CODE , g.NAME_CHS , g.PARENTID
         , cast(g.name_chs as varchar(1000)) as full_name
     from gspfunc g
     where g.id = 'HIP'
     UNION ALL
     SELECT g.id, g.CODE, g.NAME_CHS , g.PARENTID
         , cast(cte1.full_name || '-' || g.name_chs as varchar(1000))  as full_name
     FROM cte1 join gspfunc g
          ON g.parentid = cte1.id
  )
  SELECT id, code, name_chs, PARENTID, full_name
  FROM cte1
  ORDER BY cte1.full_name;