1

我在 MYSQL 中有一个用于某些 QA 论坛(例如 stackoverflow)的表“帖子”,其中包含以下示例数据。

    INSERT INTO POSTS (postID, type, parentID, QuesTitle) VALUES(1,'Q',NULL,'sometext');
    INSERT INTO POSTS (postID, type, parentID, QuesTitle) VALUES(2,'Q',NULL,'randomtext');
    INSERT INTO POSTS (postID, type, parentID, QuesTitle) VALUES(3,'A',1,NULL);
    INSERT INTO POSTS (postID, type, parentID, QuesTitle) VALUES(4,'A',1,NULL);
    INSERT INTO POSTS (postID, type, parentID, QuesTitle) VALUES(5,'Q',NULL,'titletext');
    INSERT INTO POSTS (postID, type, parentID, QuesTitle) VALUES(6,'A',1,NULL);
    INSERT INTO POSTS (postID, type, parentID, QuesTitle) VALUES(7,'A',2,NULL);
    INSERT INTO POSTS (postID, type, parentID, QuesTitle) VALUES(8,'A',2,NULL);

postID 是主键,parentID 是指 postID。一个“Q”(问题)类型的帖子可以有多个“A”(答案)帖子(由它们的 parentID 显示)。只有“Q”帖子有标题,而“A”帖子没有标题(NULL)

我想选择“A”类型的帖子以及他们的帖子 ID、他们的父 ID 和它引用的 Questitle。例如-所需的结果是-

    postID    parentID    QuesTitle
    3         1           sometext
    4         1           sometext
    6         1           sometext
    7         2           randomtext
    8         2           randomtext

使用'with'子句 CTE 会更容易,但 MYSQL 不支持它。有人可以帮助我在 MYSQL 中实现它吗?

4

2 回答 2

3

在他们的示例中,可能不清楚他们为什么要使用 CTE,但我同意如果 MySQL 能够添加这个非常缺乏的功能会非常好(提示 MariaDB 基金会)

CTE 对于任意深度的分层数据非常有用。

这是一个 postgres 示例:

CREATE TABLE posts (
    postid integer,
    type character varying(100),
    parentid integer,
    questitle character varying(100)
);
INSERT INTO posts VALUES (1, 'Q', NULL, 'sometext');
INSERT INTO posts VALUES (2, 'Q', NULL, 'randomtext');
INSERT INTO posts VALUES (3, 'A', 1, NULL);
INSERT INTO posts VALUES (4, 'A', 1, NULL);
INSERT INTO posts VALUES (5, 'Q', NULL, 'titletext');
INSERT INTO posts VALUES (6, 'A', 1, NULL);
INSERT INTO posts VALUES (7, 'A', 2, NULL);
INSERT INTO posts VALUES (8, 'A', 2, NULL);
INSERT INTO posts VALUES (9, 'A', 8, NULL);
INSERT INTO posts VALUES (10, 'A', 4, NULL);
INSERT INTO posts VALUES (11, 'A', 10, NULL);
INSERT INTO posts VALUES (12, 'A', 11, NULL);

使用以下查询:

with recursive posts_cte (postid, type, parentid, questitle,level,id_lineage)  as
(
    -- base case
    select 
        postid, type, parentid, questitle, 0 as level, ''||postid as id_lineage
    from 
        POSTS
    where 
        parentid is null

    UNION ALL

    -- recursion case
    select 
        c.postid, c.type, c.parentid, c.questitle, p.level+1 as level, p.id_lineage||','||c.postid as id_lineage
    from
        posts c
        inner join posts_cte p on
            c.parentid = p.postid
)
select
    postid, type, parentid, questitle,level,id_lineage
from
    posts_cte
order by
    id_lineage;

产生结果集:

 postid | type | parentid | questitle  | level |  id_lineage
--------+------+----------+------------+-------+--------------
      1 | Q    |          | sometext   |     0 | 1
      3 | A    |        1 |            |     1 | 1,3
      4 | A    |        1 |            |     1 | 1,4
     10 | A    |        4 |            |     2 | 1,4,10
     11 | A    |       10 |            |     3 | 1,4,10,11
     12 | A    |       11 |            |     4 | 1,4,10,11,12
      6 | A    |        1 |            |     1 | 1,6
      2 | Q    |          | randomtext |     0 | 2
      7 | A    |        2 |            |     1 | 2,7
      8 | A    |        2 |            |     1 | 2,8
      9 | A    |        8 |            |     2 | 2,8,9
      5 | Q    |          | titletext  |     0 | 5
于 2013-02-07T19:34:40.387 回答
1

为什么需要 CTE?

您可以简单地进行自加入来获取parentID的信息:

SELECT a.postID, a.parentID, b.QuesTitle
FROM   posts a
JOIN   posts b ON a.parentID = b.postID
WHERE  a.type = 'A'
于 2012-07-28T08:59:21.473 回答