最近做数据过滤觉得很有必要记录下整个过程,说不定下次就不知道了。
废话不多说开始:
表结构:
企业表(自关联,采用树的形式记录分子公司)
区域表(自关联,采用树的形式记录省/市/县/乡,数据量大)
公司管辖区域表(公司-区域的映射表,一对多,记录了公司所具有的管辖区域)
场景:根据自己的管辖区域构建区域查询条件
分子公司都有可能维护了管辖区域,上级具有下级的管辖权限(原因:上级公司有可能没有维护下级公司具有的管辖区域,而上级公司要管理下级就不需具有下级的管辖区域,所用需同时把下级的管辖区域给上级公司一次类推),在地址维护时,维护到任何级别都具有其下级区域的管辖(比如:某个公司维护了成都,它就具有成都和成都下的全部区域的管辖权限),维护到任何级别都具有该区域上级权限(比如:某个公司维护了成都/武侯区,那它就具有武侯区,成都,四川三个权限)
说到这是不是已经晕了,(拿到公司的管辖区域进行一次向上递归和一次向下递归然后合并结果集)
第一步:递归出子公司 (4319 是总部的id)
sql:SELECT *
FROM
C_COMPANY
START WITH
corp_id
=4319
CONNECT BY prior
corp_id= corp_parentid
结果:
第二步:拿出子公司的管辖区域 c_dealers_zone 管辖区域表1,c_store_zone 管辖区域表2
sql:SELECT zid
FROM
( SELECT d.c_z_id AS zid
,d.c_com_id AS comid FROM c_dealers_zone
d
UNION
SELECT s.csz_zid AS zid
,s.csz_sid AS comid FROM c_store_zone
s
)
WHERE comid
IN
(SELECT
corp_id
FROM
C_COMPANY
START WITH
corp_id
=4319
CONNECT BY prior
corp_id= corp_parentid
)
结果: 表示4319和其下级公司已维护了的管辖区域。
第三步 将管辖区域id关联到区域信息表已拿出详细信息,并同时向上递归拿出上级(以便检索出下级)
sql:SELECT DISTINCT *
FROM
c_zone
START WITH zone_id
IN
(SELECT
zid
FROM
( SELECT d.c_z_id AS zid
,d.c_com_id AS comid FROM c_dealers_zone
d
UNION
SELECT s.csz_zid AS zid
,s.csz_sid AS comid FROM c_store_zone
s
)
WHERE comid
IN
(SELECT
corp_id
FROM
C_COMPANY
START WITH
corp_id
=4319
CONNECT BY prior
corp_id= corp_parentid
)
)
CONNECT
BY zone_id=prior zone_parent
结果:去重前:
第四步 将管辖区域向下递归(维护到某个区域表示具有该区域下级管辖)
sql:SELECT *
FROM
c_zone
START WITH zone_id
IN
(SELECT
zid
FROM
( SELECT d.c_z_id AS zid
,d.c_com_id AS comid FROM c_dealers_zone
d
UNION
SELECT s.csz_zid AS zid
,s.csz_sid AS comid FROM c_store_zone
s
)
WHERE comid
IN
(SELECT
corp_id
FROM
C_COMPANY
START WITH
corp_id
=4319
CONNECT BY prior
corp_id= corp_parentid
)
)
CONNECT
BY prior zone_id=zone_parent
结果:(维护到永州市就具有永州市的子集全部管辖)
第五步,将向上递归和向下递归合并结果集作为总部的管辖区域 ,加上where条件查询指定区域下的直接子集,0:中国
sql:SELECT *
FROM
(SELECT
* from
(SELECT *
FROM
c_zone
START WITH zone_id
IN
(SELECT
zid
FROM
( SELECT d.c_z_id AS zid
,d.c_com_id AS comid FROM c_dealers_zone
d
UNION
SELECT s.csz_zid AS zid
,s.csz_sid AS comid FROM c_store_zone
s
)
WHERE comid
IN
(SELECT
corp_id
FROM
C_COMPANY
START WITH
corp_id
=4441
CONNECT BY prior
corp_id= corp_parentid
)
)
CONNECT
BY prior zone_id=zone_parent
)
UNION
( SELECT *
FROM
c_zone
START WITH zone_id
IN
(SELECT
zid
FROM
( SELECT d.c_z_id AS zid
,d.c_com_id AS comid FROM c_dealers_zone
d
UNION
SELECT s.csz_zid AS zid
,s.csz_sid AS comid FROM c_store_zone
s
)
WHERE comid
IN
(SELECT
corp_id
FROM
C_COMPANY
START WITH
corp_id
=4319
CONNECT BY prior
corp_id= corp_parentid
)
)
CONNECT
BY zone_id=prior zone_parent
)
)
WHERE
zone_parent=0
结果:不加WHERE zone_parent=0:
加WHERE zone_parent=0(只拿出省份):
整个运行也只需要100多毫米挺快的
至此已经完成区域条件构建只拿出自己所具有的区域
总结:做完感觉数据库设计的重要性。一个好的数据库设计能够使整个开发变得简单清晰,一个糟糕的数据设计完全有可能使得某个需求无法满足。
oracle 递归查询(start with …… connect by prior ……)的灵活使用 以及 union (去重) 合并结果集