【问题标题】:How to join multiple tables when creating a CTE Recursive Query创建 CTE 递归查询时如何连接多个表
【发布时间】:2022-01-04 18:46:49
【问题描述】:

我正在尝试创建一个递归查询,该查询将从 3 个不同的表中获取属性,但我无法正确 JOIN 表,因此我无法选择所需的属性:

我有 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 个表?

【问题讨论】:

  • Edit 问题并完成minimal reproducible example,即为示例数据提供INSERT 语句(粘贴文本,不要使用图像,不要链接到外部网站)(dito)以及表格文本格式的样本数据的期望结果。
  • 嘿,@stickybit 我实际上认为我的问题很完整。我应该添加问题中 3 个表中的数据吗?您能否给我更多反馈并告诉我如何改进问题?
  • 是的,正如我所写,为表格添加一些示例数据(少量就足够了)以及您想要使用该数据获得的实际结果。可以这样想:有人愿意解决您的问题并在可能的情况下为您提供解决方案。但是有人想要有一些东西可以使用,即环境的相关部分来处理解决方案并对其进行测试。为此,他们需要以可消费的方式提供样本数据(因此它应该是 INSERT 语句)和想要检查的结果,如果解决方案是正确的,并且更好地理解你想要什么。
  • 我明白了,这很好!但是其中的CREATE 语句也很有帮助,您不应该删除它们。正如我所写的,如果你真的想让愿意帮助你的人轻松一点,应该有INSERT 数据声明。
  • 谢谢。现在这是一个完美的问题! :)

标签: postgresql join common-table-expression


【解决方案1】:

解决办法如下:

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。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-05-23
    • 2023-02-21
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-25
    相关资源
    最近更新 更多