创建 CTE 递归查询时如何连接多个表
How to join multiple tables when creating a CTE Recursive Query
我正在尝试创建一个递归查询,它将从 3 个不同的表中获取属性,但我无法正确连接这些表,因此我无法 select 所需的属性:
我有 3 个表:
tb_register
CREATE TABLE olympic.tb_register (
athlete_id CHARACTER(7) NOT NULL,
round_number INT NOT NULL,
discipline_id INT NOT NULL,
register_position INT DEFAULT NULL,
CONSTRAINT pk_register PRIMARY KEY (athlete_id, round_number, discipline_id),
CONSTRAINT fk_register_athlete FOREIGN KEY (athlete_id) REFERENCES olympic.tb_athlete (athlete_id),
CONSTRAINT fk_register_round FOREIGN KEY (discipline_id, round_number) REFERENCES olympic.tb_round (discipline_id, round_number)
);
athlete_id round_number discipline_id register_position
"1349038" 3 16 0
"1393212" 3 16 1
"1318621" 3 16 2
"1451030" 3 16 3
"1343607" 3 16 4
"1435826" 3 16 5
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1349038', 3, 16, 0);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1393212', 3, 16, 1);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1318621', 3, 16, 2);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1451030', 3, 16, 3);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1343607', 3, 16, 4);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1435826', 3, 16, 5);
tb_athlete
CREATE TABLE olympic.tb_athlete (
athlete_id CHARACTER(7) NOT NULL,
name CHARACTER VARYING(50) NOT NULL,
country CHARACTER VARYING(3) NOT NULL,
substitute_id CHARACTER(7) DEFAULT NULL,
CONSTRAINT pk_athlete PRIMARY KEY (athlete_id),
CONSTRAINT fk_athlete_substitute FOREIGN KEY (substitute_id) REFERENCES olympic.tb_athlete (athlete_id)
);
athlete_id athlete_name country
"1349038" "AALERUD Katrine" "NOR"
"1393212" "ABASS Abobakr" "SUD"
"1451030" "ABDALLA Abubaker Haydar" "QAT"
"1444255" "ABDEL LATIF Radwa" "EGY"
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1346266','AALERUD Katrine','NOR',NULL);
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1344792','ABASS Abobakr','SUD',NULL);
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1328854','ABDALLA Abubaker Haydar','QAT',NULL);
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1306332','ABDEL LATIF Radwa','EGY',NULL);
tb_discipline
CREATE TABLE olympic.tb_discipline (
discipline_id INT NOT NULL,
name CHARACTER VARYING(50) NOT NULL,
inventor CHARACTER VARYING(50) NOT NULL,
type CHARACTER VARYING(10) NOT NULL,
object_type CHARACTER VARYING(20) DEFAULT NULL,
CONSTRAINT ck_discipline_type CHECK (type IN ('RUN', 'JUMP', 'THROW')),
CONSTRAINT pk_discipline PRIMARY KEY (discipline_id)
);
discipline_id discipline_name inventor type
16 "Triathlon" "Carina Melina" "RUN"
INSERT INTO olympic.tb_discipline(discipline_id, name, inventor, type, object_type) VALUES(16,'Triathlon','Carina Melina','RUN',null);
期望输出
我正在尝试创建递归查询以获得此结果:
discipline_name, round_number, register_position, a_position
Triathlon, 3, 0, 0:AALERUD Katrine,
Triathlon, 3, 1, 0:AALERUD Katrine -> 1: ABASS Abobakr
Triathlon, 3, 2, 0:AALERUD Katrine -> 1: ABASS Abobakr -> ABDALLA Abubaker Haydar
其中 a_position 是运动员姓名及其各自位置的列表。
我的代码:
WITH RECURSIVE athlete_hierarchy AS (
SELECT
discipline_name,
round_number,
register_position,
CAST (athlete_name AS TEXT) AS a_position,
register_position AS first_athlete
FROM
olympic.tb_register
JOIN tb_discipline
ON discipline_id = tb_discipline.discipline_id
JOIN tb_athlete
ON athlete_id = tb_athlete.athlete_id;
WHERE
round_number IS 3
UNION ALL
SELECT
a.discipline_name,
a.round_number,
a.register_position,
CAST ( a.athlethe_name || ' -> ' || a2.a_position AS TEXT) AS a_position,
c2.first_athlete AS first_athlete
FROM
olympic.tb_register INNER JOIN athlete_hierarchy
ON (a.athlete_id = a2.athlete_id)
)
SELECT
discipline_name,
round_number,
register_position,
a_position,
first_athlete
FROM athlete_hierarchy;
任何人都可以帮助我了解如何在创建 CTE 递归查询时连接 3 个表吗?
这是解决方案:
WITH RECURSIVE athlete_hierarchy (discipline_id, discipline_name, round_number, register_position, a_position) AS
(SELECT
d.discipline_id,
d.name,
r.round_number,
r.register_position,
r.register_position || ':' || CAST (a.name AS TEXT)
FROM tb_register AS r
JOIN tb_discipline AS d
ON r.discipline_id = d.discipline_id
JOIN tb_athlete AS a
ON r.athlete_id = a.athlete_id
WHERE r.round_number = 3
AND r.register_position = 0
UNION ALL
SELECT
ah.discipline_id,
ah.discipline_name,
ah.round_number,
r.register_position,
ah.a_position || ' -> ' || r.register_position || ':' || CAST (a.name AS TEXT)
FROM tb_register AS r
INNER JOIN athlete_hierarchy AS ah
ON ah.discipline_id = r.discipline_id
AND ah.round_number = r.round_number
AND ah.register_position = r.register_position - 1
INNER JOIN tb_athlete AS a
ON r.athlete_id = a.athlete_id
)
SELECT discipline_name, round_number, register_position, a_position
FROM athlete_hierarchy
ORDER BY register_position
并且您的数据样本的测试结果在 db<>fiddle.
我正在尝试创建一个递归查询,它将从 3 个不同的表中获取属性,但我无法正确连接这些表,因此我无法 select 所需的属性:
我有 3 个表:
tb_register
CREATE TABLE olympic.tb_register (
athlete_id CHARACTER(7) NOT NULL,
round_number INT NOT NULL,
discipline_id INT NOT NULL,
register_position INT DEFAULT NULL,
CONSTRAINT pk_register PRIMARY KEY (athlete_id, round_number, discipline_id),
CONSTRAINT fk_register_athlete FOREIGN KEY (athlete_id) REFERENCES olympic.tb_athlete (athlete_id),
CONSTRAINT fk_register_round FOREIGN KEY (discipline_id, round_number) REFERENCES olympic.tb_round (discipline_id, round_number)
);
athlete_id round_number discipline_id register_position
"1349038" 3 16 0
"1393212" 3 16 1
"1318621" 3 16 2
"1451030" 3 16 3
"1343607" 3 16 4
"1435826" 3 16 5
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1349038', 3, 16, 0);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1393212', 3, 16, 1);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1318621', 3, 16, 2);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1451030', 3, 16, 3);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1343607', 3, 16, 4);
INSERT INTO olympic.tb_register(athlete_id, round_number, discipline_id, register_position) VALUES('1435826', 3, 16, 5);
tb_athlete
CREATE TABLE olympic.tb_athlete (
athlete_id CHARACTER(7) NOT NULL,
name CHARACTER VARYING(50) NOT NULL,
country CHARACTER VARYING(3) NOT NULL,
substitute_id CHARACTER(7) DEFAULT NULL,
CONSTRAINT pk_athlete PRIMARY KEY (athlete_id),
CONSTRAINT fk_athlete_substitute FOREIGN KEY (substitute_id) REFERENCES olympic.tb_athlete (athlete_id)
);
athlete_id athlete_name country
"1349038" "AALERUD Katrine" "NOR"
"1393212" "ABASS Abobakr" "SUD"
"1451030" "ABDALLA Abubaker Haydar" "QAT"
"1444255" "ABDEL LATIF Radwa" "EGY"
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1346266','AALERUD Katrine','NOR',NULL);
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1344792','ABASS Abobakr','SUD',NULL);
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1328854','ABDALLA Abubaker Haydar','QAT',NULL);
INSERT INTO olympic.tb_athlete(athlete_id, name, country, substitute_id) VALUES('1306332','ABDEL LATIF Radwa','EGY',NULL);
tb_discipline
CREATE TABLE olympic.tb_discipline (
discipline_id INT NOT NULL,
name CHARACTER VARYING(50) NOT NULL,
inventor CHARACTER VARYING(50) NOT NULL,
type CHARACTER VARYING(10) NOT NULL,
object_type CHARACTER VARYING(20) DEFAULT NULL,
CONSTRAINT ck_discipline_type CHECK (type IN ('RUN', 'JUMP', 'THROW')),
CONSTRAINT pk_discipline PRIMARY KEY (discipline_id)
);
discipline_id discipline_name inventor type
16 "Triathlon" "Carina Melina" "RUN"
INSERT INTO olympic.tb_discipline(discipline_id, name, inventor, type, object_type) VALUES(16,'Triathlon','Carina Melina','RUN',null);
期望输出
我正在尝试创建递归查询以获得此结果:
discipline_name, round_number, register_position, a_position
Triathlon, 3, 0, 0:AALERUD Katrine,
Triathlon, 3, 1, 0:AALERUD Katrine -> 1: ABASS Abobakr
Triathlon, 3, 2, 0:AALERUD Katrine -> 1: ABASS Abobakr -> ABDALLA Abubaker Haydar
其中 a_position 是运动员姓名及其各自位置的列表。
我的代码:
WITH RECURSIVE athlete_hierarchy AS (
SELECT
discipline_name,
round_number,
register_position,
CAST (athlete_name AS TEXT) AS a_position,
register_position AS first_athlete
FROM
olympic.tb_register
JOIN tb_discipline
ON discipline_id = tb_discipline.discipline_id
JOIN tb_athlete
ON athlete_id = tb_athlete.athlete_id;
WHERE
round_number IS 3
UNION ALL
SELECT
a.discipline_name,
a.round_number,
a.register_position,
CAST ( a.athlethe_name || ' -> ' || a2.a_position AS TEXT) AS a_position,
c2.first_athlete AS first_athlete
FROM
olympic.tb_register INNER JOIN athlete_hierarchy
ON (a.athlete_id = a2.athlete_id)
)
SELECT
discipline_name,
round_number,
register_position,
a_position,
first_athlete
FROM athlete_hierarchy;
任何人都可以帮助我了解如何在创建 CTE 递归查询时连接 3 个表吗?
这是解决方案:
WITH RECURSIVE athlete_hierarchy (discipline_id, discipline_name, round_number, register_position, a_position) AS
(SELECT
d.discipline_id,
d.name,
r.round_number,
r.register_position,
r.register_position || ':' || CAST (a.name AS TEXT)
FROM tb_register AS r
JOIN tb_discipline AS d
ON r.discipline_id = d.discipline_id
JOIN tb_athlete AS a
ON r.athlete_id = a.athlete_id
WHERE r.round_number = 3
AND r.register_position = 0
UNION ALL
SELECT
ah.discipline_id,
ah.discipline_name,
ah.round_number,
r.register_position,
ah.a_position || ' -> ' || r.register_position || ':' || CAST (a.name AS TEXT)
FROM tb_register AS r
INNER JOIN athlete_hierarchy AS ah
ON ah.discipline_id = r.discipline_id
AND ah.round_number = r.round_number
AND ah.register_position = r.register_position - 1
INNER JOIN tb_athlete AS a
ON r.athlete_id = a.athlete_id
)
SELECT discipline_name, round_number, register_position, a_position
FROM athlete_hierarchy
ORDER BY register_position
并且您的数据样本的测试结果在 db<>fiddle.