Given the following table of sports matches with two players:
| match_id | match_date | p1_id | p2_id |
|---|---|---|---|
| 1 | 01/01/2022 | 1 | 2 |
| 2 | 02/01/2022 | 3 | 1 |
| 3 | 03/01/2022 | 3 | 4 |
| 4 | 04/01/2022 | 2 | 3 |
| 5 | 05/01/2022 | 5 | 6 |
| 6 | 06/01/2022 | 1 | 2 |
| 7 | 07/01/2022 | 3 | 1 |
| 8 | 08/01/2022 | 3 | 4 |
| 9 | 09/01/2022 | 2 | 3 |
| 10 | 10/01/2022 | 5 | 6 |
| 11 | 11/01/2022 | 3 | 4 |
| 12 | 12/01/2022 | 7 | 8 |
| 13 | 13/01/2022 | 3 | 1 |
| 14 | 14/01/2022 | 5 | 7 |
| 15 | 15/01/2022 | 4 | 5 |
I’m trying to write a query with a recursive CTE that when given a match_id the query will return all match_id values for future matches for each of the two players. The recursion is needed because I need the query to also include all future matches for any of the future matches' players.
Using the example above and match_id = 6 then the two player IDs are 1 and 2. I need the query to return all future matches for these player IDs. This means the query needs to return 7, 9 and 13. However, in match_id = 7 player ID 1 plays player ID 3 so now all of their future match_id values from that point also need to be included. This means the query also needs to return 8 and 11. In match_id = 8 and match_id = 11 player ID 3 plays player ID 4 so the final match_id to be returned is 15.
The expected output is as follows:
| match_id |
|---|
| 7 |
| 8 |
| 9 |
| 11 |
| 13 |
| 15 |
I've written the following query:
WITH RECURSIVE match_ids AS (
SELECT
m1.match_id,
m1.match_date,
m1.p1_id,
m1.p2_id
FROM recursive_test AS m1
WHERE m1.match_id = 6
UNION ALL
SELECT
m2.match_id,
m2.match_date,
m2.p1_id,
m2.p2_id
FROM recursive_test AS m2
INNER JOIN match_ids
ON (
match_ids.p1_id = m2.p1_id
OR match_ids.p1_id = m2.p2_id
OR match_ids.p2_id = m2.p1_id
OR match_ids.p2_id = m2.p2_id
)
AND match_ids.match_date > m2.match_date
)
SELECT match_id
FROM match_ids
However, this returns:
| match_id |
|---|
| 6 |
| 2 |
| 4 |
| 1 |
| 1 |
| 2 |
| 3 |
| 1 |
| 2 |
| 1 |
Where might I be going wrong?
Here's the SQL to create the table:
CREATE TABLE `recursive_test` (
`match_id` int NOT NULL,
`match_date` date NOT NULL,
`p1_id` int NOT NULL,
`p2_id` int NOT NULL,
PRIMARY KEY (`match_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
INSERT INTO `recursive_test` VALUES (1,'2022-01-01',1,2),(2,'2022-01-02',3,1),(3,'2022-01-03',3,4),(4,'2022-01-04',2,3),(5,'2022-01-05',5,6),(6,'2022-01-06',1,2),(7,'2022-01-07',3,1),(8,'2022-01-08',3,4),(9,'2022-01-09',2,3),(10,'2022-01-10',5,6),(11,'2022-01-11',3,4),(12,'2022-01-12',7,8),(13,'2022-01-13',3,1),(14,'2022-01-14',5,7),(15,'2022-01-15',4,5);
CodePudding user response:
WITH RECURSIVE
cte AS (
SELECT *
FROM recursive_test
WHERE match_id = @starting_match_id
UNION ALL
SELECT recursive_test.*
FROM recursive_test
JOIN cte ON recursive_test.match_date > cte.match_date
WHERE recursive_test.p1_id IN (cte.p1_id, cte.p2_id)
OR recursive_test.p2_id IN (cte.p1_id, cte.p2_id)
)
SELECT DISTINCT *
FROM cte;
https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=6ca1e57845bae995bacb04455beb6340
