postgresql中的递归函数

postgresql中的递归函数,sql,postgresql,Sql,Postgresql,我有这张桌子: CREATE TABLE players ( winner CHARACTER VARYING(50) NOT NULL , successor CHARACTER VARYING(50) NOT NULL , data NUMERIC(6,2) NOT NULL , CONSTRAINT pk_win_succ PRIMARY KEY (winner, successor) );

我有这张桌子:

CREATE TABLE players
(
    winner            CHARACTER VARYING(50) NOT NULL ,
    successor              CHARACTER VARYING(50) NOT NULL ,
    data           NUMERIC(6,2) NOT NULL ,
    CONSTRAINT pk_win_succ PRIMARY KEY (winner, successor)
);
数据:

  INSERT INTO players VALUES
  ('Helen','Sharon',12),
  ('Claudia','Steffi',35),
  ('Sharon','Penny',5),
  ('Meg','Claudia',21),
  ('Penny','Meg',3)
  ('Steffi','Helen',230);
我需要做的是一个SQL查询,它为我提供了玩家之间可能的不同组合

如果我选择球员Sharon作为首字母,选择球员Meg作为最终字母,则查询结果应为:

Initial | Final | List of winners | Total Data | Number of Winners |
Sharon | Meg | Sharon - Penny - Meg | 8 | 3
Initial | Final | List of winners | Total Data | Number of Winners |
Claudia | Sharon | Claudia - Steffi - Helen - Sharon | 277 | 4
如果我选择球员克劳迪娅作为首字母,选择球员沙龙作为最终字母,那么查询结果应该是:

Initial | Final | List of winners | Total Data | Number of Winners |
Sharon | Meg | Sharon - Penny - Meg | 8 | 3
Initial | Final | List of winners | Total Data | Number of Winners |
Claudia | Sharon | Claudia - Steffi - Helen - Sharon | 277 | 4

谢谢大家!

可以通过递归查询构建从Sharon到Meg的链:

 WITH RECURSIVE chain(winner, successor, data, active) AS (
   SELECT winner, successor, data, true
     FROM players
     WHERE winner = 'Sharon'
   UNION ALL
   SELECT p.winner, p.successor, p.data
         ,CASE WHEN p.successor = 'Meg' OR NOT c.active THEN false ELSE true END
     FROM players p
     JOIN chain c ON (p.winner = c.successor AND c.active)
 )
 SELECT * FROM chain
结果:

Sharon;Penny;5.00;t
Penny;Meg;3.00;f
然后,可以将结果集聚合为所需的格式:

 WITH RECURSIVE chain(winner, successor, data, active) AS (
   SELECT winner, successor, data, true
     FROM players
     WHERE winner = 'Sharon'
   UNION ALL
   SELECT p.winner, p.successor, p.data
         ,CASE WHEN p.successor = 'Meg' OR NOT c.active THEN false ELSE true END
     FROM players p
     JOIN chain c ON (p.winner = c.successor AND c.active)
 )
 SELECT 'Sharon' AS Initial
       ,'Meg' AS Final
       ,'Sharon - ' || string_agg(successor, ' - ') AS Winners
       ,sum(data) AS Total
       ,count(*) + 1 AS WinnerCount
   FROM chain
或参数化:

PREPARE plan(text, text) AS

 WITH RECURSIVE chain(winner, successor, data, active) AS (
   SELECT winner, successor, data, true
     FROM players
     WHERE winner = $1
   UNION ALL
   SELECT p.winner, p.successor, p.data
         ,CASE WHEN p.successor = $2 OR NOT c.active THEN false ELSE true END
     FROM players p
     JOIN chain c ON (p.winner = c.successor AND c.active)
)
SELECT $1 AS Initial
      ,$2 AS Final
      ,$1 || ' - ' || string_agg(successor, ' - ') AS Winners
      ,sum(data) AS Total
      ,count(*) + 1 AS WinnerCount
  FROM chain
;

EXECUTE plan('Sharon', 'Meg');

EXECUTE plan('Claudia', 'Sharon');

你是在寻找一条从一个玩家到另一个玩家的“链条”吗。这是什么?如果是这样,你最好的朋友就是一个图形数据库。