【问题标题】:Tricky CTE - recursive sql (editing my query)棘手的 CTE - 递归 sql(编辑我的查询)
【发布时间】:2019-11-24 18:39:54
【问题描述】:

我想编辑我的查询,以便获得更有趣的内容。

目标是获得每个客户的批准工作流程,以这种方式显示该信息:

客户 |批准人1 |批准人2 |批准人3 |批准人4

以前,我有一个名为实体的表

(12, 'Math Andrew', 308, 'CHAIN1-MathAndrew')
(13, 'John Connor', 308, 'CHAIN2-JohnConnor')
(18, 'ZATCH', 309, null),
(19, 'MAX', 309, null),
(20, 'Ger',310, null),
(21, 'Mar',310, null),
(22, 'Maxwell',311, null),
(23, 'Ryan',312, null),
(24, 'Juy',313, null),
(25, 'Angel',314, null),
(26, 'John',315, null);

请注意:

12 被分配给 Math Andrew... 308 是表示 马特安德鲁是客户

13 被分配给 John Connor...308 是表示 John Connor 是客户的数字

因为 Math Andrew 和 John Connor 是客户(也称为 CUSTOMERS),所以他们必须与一个或多个 APPROVERS 相关联

一个客户可能有 1 个审批者,或 2 个审批者或 3 个审批者或 4 个审批者,实体表中存在不同的审批者。

当我说客户“可能”有 1 个或多个 APPROVERS 时,我的意思是:

CLIENT - APPROOVER4(这是 1-1 关系) PS:A CLIENT WILL 始终以某种方式与批准者4相关

CLIENT - APPROVER1 - APPROVER4(在这种情况下将有 2 关系.. 一个:CLIENT-APPROVER1 和另一个 APPROVER1-APPROVER4)

CLIENT - APPROVER1 - APPROVER2 - APPROVER4(在这种情况下将有 3 个关系.. 一个:CLIENT-APPROVER1、APPROVER1-APPROVER2 和 批准人2 - 批准人4)

等等……(希望你明白)

表类型_实体

(308,'CLIENT'),
(309,'APPROVER1'),
(310,'APPROVER2'),
(311,'APPROVER3'),
(312,'J3 APPROVER4'),
(313,'J4 APPROVER4'),
(314,'J5 APPROVER4'),
(315, 'J6 APPROVER4'),
(316,'J7 APPROVER4');

表类型关系

(444,'J6 CLIENT-APPROVER4'),
(445,'J3 CLIENT-APPROVER4'),
(446,'J4 CLIENT-APPROVER4'),
(447,'J10 CLIENT-APPROVER4'),
(449,'J5 CLIENT-APPROVER4'),
(453,'J5 CLIENT-APPROVER4'),
(456,'J7 CLIENT-APPROVER4'),
(457,'J8 CLIENT-APPROVER4'),
(458,'CLIENT-APPROVER3'),
(459,'CLIENT-APPROVER1'),
(460,'APPROVER1-APPROVER2'),
(461,'APPROVER1-APPROVER3'),
(462,'J3 APPROVER1-APPROVER4'),
(463,'APPROVER2-APPROVER3'),
(464,'J3 APPROVER3-APPROVER4'),
(465,'J4 APPROVER3-APPROVER4'),
(466,'J5 APPROVER3-APPROVER4'),
(467,'J6 APPROVER3-APPROVER4'),
(468,'J7 APPROVER3-APPROVER4'),
(469,'J8 APPROVER3-APPROVER4'),
(470,'J10 APPROVER3-APPROVER4'),
(471,'CLIENT-APPROVER2');

关系类型:

客户 - 批准人 1:

(459,'CLIENT-APPROVER1') 

客户 - 批准人 2:

(471,'CLIENT-APPROVER2') 

客户 - 批准人3:

(461,'APPROVER1-APPROVER3')

客户 - 批准人4:

(445,'J3 CLIENT-APPROVER4'),
(446,'J4 CLIENT-APPROVER4'),
(449,'J5 CLIENT-APPROVER4'),
(444,'J6 CLIENT-APPROVER4'),
(456,'J7 CLIENT-APPROVER4'),
(457,'J8 CLIENT-APPROVER4'),
(447,'J10 CLIENT-APPROVER4');

审批者 1 -审批者 2:

(460,'APPROVER1-APPROVER2')

审批者 2 - 审批者 3:

(463,'APPROVER2-APPROVER3')

审批者 3 - 审批者 4:

(464,'J3 APPROVER3-APPROVER4'),
(465,'J4 APPROVER3-APPROVER4'),
(466,'J5 APPROVER3-APPROVER4'),
(467,'J6 APPROVER3-APPROVER4'),
(468,'J7 APPROVER3-APPROVER4'),
(469,'J8 APPROVER3-APPROVER4'),
(470,'J10 APPROVER3-APPROVER4');

这很重要:当客户链接到一个审批者时,一个新的 RELATION 是在关系表中创建的。

表关系:

(787,459,12,18),
(788,460,18,20),
(789,463,20,21),
(790,467,21,26);

787 是创建该行时分配的编号

459 代表关系:客户 - 批准人

12 CHAIN1-MathAndre 是客户端

18 是批准人

遵循这个想法:

APPROVER1 已链接到 APPROVER2:

(788,460,18,20)

APPROVER2 已链接到 APPROVER3:

(789,463,20,21)

APPROVER3 已链接到 APPROVER4:

(790,467,21,26) ​

所以,我在屏幕上显示这个:

|CLIENT               | APPROVER1 | APPROVER2 | APPROVER3 | APPROVER4|
|CHAIN1-MathAndrew    |   ZATCH   |   Ger     |    Mar    |    John  |
|CHAIN2-JohnConnor    |    MAX    |           |    Mario  |    Steven|
|CHAIN3-MarioShapiro  |    IVAN   |           |           |    John  |

这是我的小提琴:

fiddle

这是我的查询:

WITH recursive relationships_CTE as (
  select e.id, e.description AS name, 1 col_id, 
    row_number() over (order by e.id) row_id
  from entities e
  where e.description like 'CHAIN%'
    UNION ALL
  select r.description_entitiy_2, e.name, col_id+ 1, row_id
  from relationships_CTE cte
  left join relationships r
    on r.description_entitiy_1 = cte.id
  join entities e 
    on r.description_entitiy_2 = e.id
)
select 
  max(case when col_id = 1 then name end) client,
  max(case when col_id = 2 then name end) approver1,
  max(case when col_id = 3 then name end) approver2,
  max(case when col_id = 4 then name end) approver3,
  max(case when col_id = 5 then name end) approver4
from relationships_CTE
group by row_id

现在,这就是我想要做的:

假设我有一个名为 new_table 的新表,并且我稍微修改了表实体:

(12, 'Math Andrew', 308, 45)
(13, 'John Connor', 308, 46)
(18, 'ZATCH', 309, null),
(19, 'MAX', 309, null),
(20, 'Ger',310, null),
(21, 'Mar',310, null),
(22, 'Maxwell',311, null),
(23, 'Ryan',312, null),
(24, 'Juy',313, null),
(25, 'Angel',314, null),
(26, 'John',315, null);

table new_table

(45,'Math Andrew', 'Chain1')
(45,'Math Andrew', 'Chain2')
(46, 'John Connor', 'Chain1')
(46, ''John Connor', 'Chain2')

表格关系会是这样的:

(787,459,'45-Chain1',18)
(788,460,18,20)
(789,463,20,21)
(790,467,21,26)

所以,我想将表 entities 与表 new_table 连接起来,得到关系 45-Chain1,然后在表关系中找到 45-Chain1 并得到类似的东西(并对所有不同的客户做同样的事情):

|CLIENT               | APPROVER1 | APPROVER2 | APPROVER3 | APPROVER4|
|45-Chain1            |   ZATCH   |   Ger     |    Mar    |    John  |

我一直在尝试解决这个问题。

你能帮帮我吗?

【问题讨论】:

  • 得说,这是一个相当大的问题。没有多少次我想知道滚动何时结束。
  • 嘿,你好吗?是的!我想解释一切! :)
  • 它建议如果你可以保持你的查询简短,因为它很容易解决然后
  • 嗨@HimanshuAhuja,你好吗?什么意思?
  • 他们的意思是这里的信息太多了。将其简化为仅回答问题所需的信息。

标签: mysql sql common-table-expression recursive-query


【解决方案1】:

我试过了。
并进行了一些额外的规范化,添加了一个chains 表。

这是我的尝试:

create table entity_types 
(
 entity_type_id int primary key, 
 entity_type_name varchar(32) not null
);
create table relation_types 
(
 relation_type_id int primary key, 
 relation_type_name varchar(32) not null
);
create table chains 
(
 chain_id int primary key,
 chain_name varchar(30) not null
);
create table entities 
(
 entity_id int primary key,
 entity_name varchar(32) not null, 
 entity_type_id int not null,
 chain_id int,
 foreign key (entity_type_id)
         references entity_types(entity_type_id),
 foreign key (chain_id)
         references chains(chain_id)
);
create table relationships 
(
 relationship_id int primary key, 
 relation_type_id int not null,
 entity_id_1 int not null,
 entity_id_2 int not null,
 foreign key (relation_type_id)
         references relation_types(relation_type_id)
);
create table entity_chains 
(
 entity_id int not null,
 chain_id int not null,
 primary key (entity_id, chain_id),
 foreign key (chain_id)
         references chains(chain_id),
 foreign key (entity_id) 
         references entities(entity_id)
);
INSERT INTO entity_types
(entity_type_id, entity_type_name) VALUES
(308,'CLIENT'),
(309,'APPROVER1'),
(310,'APPROVER2'),
(311,'APPROVER3'),
(312,'J3 APPROVER4'),
(313,'J4 APPROVER4'),
(314,'J5 APPROVER4'),
(315,'J6 APPROVER4'),
(316,'J7 APPROVER4');
INSERT INTO relation_types
(relation_type_id, relation_type_name) VALUES
(444,'J6 CLIENT-APPROVER4'),
(445,'J3 CLIENT-APPROVER4'),
(446,'J4 CLIENT-APPROVER4'),
(447,'J10 CLIENT-APPROVER4'),
(448,'J4 CLIENT-APPROVER4'),
(449,'J5 CLIENT-APPROVER4'),
(450,'J10 CLIENT-APPROVER4'),
(451,'J3 CLIENT-APPROVER4'),
(452,'J8 CLIENT-APPROVER4'),
(453,'J5 CLIENT-APPROVER4'),
(454,'J6 CLIENT-APPROVER4'),
(455,'J7 CLIENT-APPROVER4'),
(456,'J7 CLIENT-APPROVER4'),
(457,'J8 CLIENT-APPROVER4'),
(458,'CLIENT-APPROVER3'),
(459,'CLIENT-APPROVER1'),
(460,'APPROVER1-APPROVER2'),
(461,'APPROVER1-APPROVER3'),
(462,'J3 APPROVER1-APPROVER4'),
(463,'APPROVER2-APPROVER3'),
(464,'J3 APPROVER3-APPROVER4'),
(465,'J4 APPROVER3-APPROVER4'),
(466,'J5 APPROVER3-APPROVER4'),
(467,'J6 APPROVER3-APPROVER4'),
(468,'J7 APPROVER3-APPROVER4'),
(469,'J8 APPROVER3-APPROVER4'),
(470,'J10 APPROVER3-APPROVER4'),
(471,'CLIENT-APPROVER2');
insert into chains 
(chain_id, chain_name) values
(45,'Chain1'),
(46,'Chain2');
INSERT INTO entities 
(entity_id, entity_name, 
 entity_type_id, chain_id) VALUES
(12, 'Math Andrew', 308, 45),
(13, 'John Connor', 308, 46),
(18, 'ZATCH', 309, null),
(19, 'MAX', 309, null),
(20, 'Ger',310, null),
(21, 'Mar',310, null),
(22, 'Maxwell',311, null),
(23, 'Ryan',312, null),
(24, 'Juy',313, null),
(25, 'Angel',314, null),
(26, 'John',315, null);
INSERT INTO relationships 
(relationship_id, relation_type_id,
 entity_id_1, entity_id_2) VALUES
(787,459,12,18),
(788,460,18,20),
(789,463,20,21),
(790,467,21,26);
insert into entity_chains 
(entity_id, chain_id) values
(12, 45),
(12, 46),
(13, 45),
(13, 46);
WITH RECURSIVE RCTE AS
(
  SELECT
   ent.chain_id,
   entch.entity_id as entity_id_0,
   0 as lvl,
   0 as entity_id_1,
   entch.entity_id as entity_id_2,
   0 as relation_type_id
  FROM entities ent
  JOIN entity_chains entch
    ON entch.chain_id = ent.chain_id

  UNION ALL

  SELECT 
  cte.chain_id,
  cte.entity_id_0,
  lvl+1,
  rel.entity_id_1,
  rel.entity_id_2,
  rel.relation_type_id
  FROM RCTE cte
  JOIN relationships rel
    ON rel.entity_id_1 = cte.entity_id_2
),
CTE AS
(
  SELECT
  rcte.*,
  chains.chain_name,
  ent0.entity_name as entity_name_0,
  -- reltype.relation_type_name,
  -- enttype2.entity_type_name as entity_type_name_2,
  -- ent1.entity_name as entity_name_1,
  ent2.entity_name as entity_name_2
  FROM RCTE rcte
  JOIN chains ON chains.chain_id = rcte.chain_id
  JOIN entities ent0 ON ent0.entity_id = rcte.entity_id_0
  JOIN entities ent2 ON ent2.entity_id = rcte.entity_id_2
  -- LEFT JOIN entity_types enttype2 ON enttype2.entity_type_id = ent2.entity_type_id
  -- LEFT JOIN relation_types reltype ON reltype.relation_type_id = rcte.relation_type_id
  -- LEFT JOIN entities ent1 ON ent1.entity_id = rcte.entity_id_1
)
/*
SELECT * FROM CTE WHERE lvl > 0
ORDER BY chain_name, entity_id_0, lvl;
*/
SELECT 
REPLACE(CONCAT(entity_name_0,'-',chain_name),' ','') as chain_client,
max(case when lvl=1 then entity_name_2 end) as approver1,
max(case when lvl=2 then entity_name_2 end) as approver2,
max(case when lvl=3 then entity_name_2 end) as approver3,
max(case when lvl=4 then entity_name_2 end) as approver4
FROM CTE cte
WHERE lvl > 0
GROUP BY chain_name, entity_name_0
ORDER BY chain_client;
链客户端 |批准人1 |批准人2 |批准人3 |批准人4 :---------------- | :-------- | :-------- | :-------- | :-------- 数学Andrew-Chain1 |扎奇 |德语 |三月 |约翰 数学Andrew-Chain2 |扎奇 |德语 |三月 |约翰

db小提琴here

【讨论】:

  • 非常感谢你帮助我!,我正在检查这个:)
  • 哥们,能不能把RCTE里面的栏目补全?
  • 问题是我需要显示这个:45-Chain1(45是代表Math Andrew的代码):/
  • 老兄,在递归中不链接额外的表是一种选择!顺便说一句,更新了。
猜你喜欢
  • 1970-01-01
  • 2016-01-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-12
  • 1970-01-01
  • 2014-08-13
  • 1970-01-01
相关资源
最近更新 更多