已掉线,重新登录

首页 > 绿虎论坛 > 历史版块 > 编程 > 其他编程语言 > 讨论/求助

标题: 问一个需要递归的SQL

作者: @Ta

时间: 2022-10-09发布,2022-10-09修改

点击: 2350

image.png(30.36 KB)

Mysql5.7(其实是 SqlServer)
目前我的尝试, 只能递归出 所有的符合浙江省的 ,市,区,街道,不能 把 区、街道 归入到市

;with org_union  as (
  select id,name ,parent_id from org where  parent_id=1 
  UNION ALL
  select   org.id, org.name,org.parent_id  as level from org  org  JOIN org_union on org.parent_id=org_union.id


  --统计区&市 级别,level为3&2,隶属于parent_id=1 浙江省
)


SELECT top 500  org_union.org_name ,count(org_union.org_name) as CountNum,sum(order.price) as TotalTncome

from org_union as org_union 

LEFT join order as  order on  org_union.id=order.apply_org_id  

where order.pay_state=2

GROUP BY  org_union.name

[隐藏样式|查看源码]


『回复列表(13|隐藏机器人聊天)』

1.

@胡椒舰长,可以用 (Recursive) CTE,也可以直接几层 JOIN (因为你的 area_level 层数有限)

(/@Ta/2022-10-09 10:56//)

2.

@无名啊,层数是没有上限的,这里只是测试,怎么怎么想办法递归的时候统计

(/@Ta/2022-10-09 11:11//)

3.

@胡椒舰长,不会吧,area_level 还能有十几层嘛。。这是精确到一口井的收入了嘛。。

(/@Ta/2022-10-09 11:13//)

4.

@胡椒舰长,这是 (Recursive) CTE 的一个例子

结果

地级市 总收入 无用列
杭州市机构 7.13 1
温州市机构 1.03 1
宁波市机构 1.32 1

SQLite 实现

(用 SQLite 意为:连 1~2 MB 的 SQLite 都支持的功能,其他数据库肯定都支持,容易移植)

WITH RECURSIVE
  
  query(root_name) AS (
    VALUES ('浙江省机构')
  ),
  
  org(id, parent_id, name, area_level) AS (
    VALUES
      ( 8001,  1001, '浙江省机构', 2),
      (10000,  8001, '杭州市机构', 3),
      (10001,  8001, '温州市机构', 3),
      (10002,  8001, '宁波市机构', 3),
      (10003, 10000, '杭州市西湖区机构', 4),
      (10004, 10003, '杭州市西湖区学院路机构', 5),
      (10005, 'xxx', '安徽省', 2)
  ),
  
  orders(org_id, price) AS (
    VALUES
      (10001, 1.03),
      (10002, 1.32),
      (10003, 3.11),
      (10004, 4.02)
  ),
  
  -- 查询 query.root_name 之下所有地区信息,第一层作为 root_id
  -- (这个例子中,地级市作为 root_id)
  all_areas_under(root_id, org_id, org_name, level) AS (
    SELECT NULL, org.id, org.name, 0
      FROM query
      JOIN org ON org.name = query.root_name
     UNION ALL
    SELECT IFNULL(root_id, org.id), org.id, org.name, level + 1
      FROM all_areas_under a
      JOIN org ON org.parent_id = a.org_id
  )

SELECT org_name '地级市', sum(price) '总收入', MIN(level) '无用列'
  FROM all_areas_under
  LEFT JOIN orders USING(org_id)
 WHERE root_id IS NOT NULL
 GROUP BY root_id;
(/@Ta/2022-10-09 11:41//)

5.

@无名啊, 这个 统计地级市的时候,需要把 他下面的 县,街道,村,生产队 的订单 都要统计归入到 市

(/@Ta/2022-10-09 11:45//)

6.

@胡椒舰长,统计了呀,你瞅瞅 杭州市 的总收入,是不是 7.13

(/@Ta/2022-10-09 11:47//)

7.

@胡椒舰长,这是直接几层 JOIN 的例子:

结果

地级市 总收入
杭州市机构 7.13
温州市机构 1.03
宁波市机构 1.32

SQLite 实现

... 省略的内容,参考 4 楼)

WITH
  
  query(root_name) AS (
    VALUES ('浙江省机构')
  ),
  
  org(id, parent_id, name, area_level) AS (...),
  
  orders(org_id, price) AS (...)

SELECT o1.name '地级市',
       IFNULL(p1.price, 0) + IFNULL(p2.price, 0) + IFNULL(p3.price, 0) '总收入'
  FROM query
  JOIN org o0 ON o0.name = query.root_name
  LEFT JOIN org o1 ON o1.parent_id = o0.id
  LEFT JOIN org o2 ON o2.parent_id = o1.id
  LEFT JOIN org o3 ON o3.parent_id = o2.id
  LEFT JOIN orders p1 ON p1.org_id = o1.id
  LEFT JOIN orders p2 ON p2.org_id = o2.id
  LEFT JOIN orders p3 ON p3.org_id = o3.id;
(/@Ta/2022-10-09 12:11//)

8.

@胡椒舰长,感觉 area_level 是无用列。。(反正我没用到)

(/@Ta/2022-10-09 12:08//)

9.

@无名啊,level还是有用的,因为他有一些地方他的parent_ID是杭州的,但是他的level是可能是 4 5 6 7,这些就是杭州市直接管理的,所以他统计的时候还有一个是浙江省直辖
机构

(/@Ta/2022-10-09 12:12//)

10.

@胡椒舰长,噢噢,可能你其他查询有用到吧

上面那俩能正常工作嘛?

(/@Ta/2022-10-09 12:19//)

11.

@无名啊还没呢我中午休息到2:00

(/@Ta/2022-10-09 12:32//)

12.

@胡椒舰长,如果你的 org 表很大,且不常更新的话,改成 嵌套集合模型Nested Set Model,也称左右值树),可以加速查询“某地区下的所有地区

(因为这种树结构只需一次 FROM org WHERE id BETWEEN xxx AND yyy。而你当前的表结构,实际需要 N 次 FROM org WHERE id = ?

(/@Ta/2022-10-09 12:58//)

13.

@胡椒舰长,或者,改成 JSON 类型,应该也很快?(就看数据库 json 引擎解析性能了。SQLite 号称 1 GB/s)

(/@Ta/2022-10-09 13:10//)

回复需要登录

6月29日 05:50 星期天

本站由hu60wap6驱动

备案号: 京ICP备18041936号-1