【问题标题】:select comments with three levels选择三个级别的评论
【发布时间】:2019-08-27 13:35:30
【问题描述】:

我有存储 cmets 的表。 cmets 具有不同的深度,并且它们在一个具有 id 和 parent_id 的表中相互关联。深层次的最大值是三,我想用一个查询而不是三个查询来选择它们,并使用 foreach 三次。

评论表:

id title                           parent_id 
 1 'where are you?'                NULL
 2 "im at home"                       1
 3 "what is time in your country?" NULL 
 4 "it's 3 pm"                        3
 5 "oh that's cool"                   4

第一层是具有 parent_id = NULL 的 cmets 我使用这些查询来获取它们:

$first = $this->db->query("SELECT title FROM comment WHERE parent_id IS NULL");
    $second = $this->db->query("SELECT title FROM comment WHERE parent_id IN (SELECT id FROM comment WHERE parent_id IS NULL)");
        $third= $this->db->query("SELECT title FROM comment WHERE parent_id IN (SELECT id FROM comment WHERE parent_id IN(SELECT id FROM comment WHERE parent_id IS NULL))");

有没有办法通过一个查询来获取它们?

【问题讨论】:

  • 您使用的是哪个版本的 MySQL?
  • 如果您使用 MySQL 8,请查看递归 CTE:dev.mysql.com/doc/refman/8.0/en/…
  • @ragol 我不熟悉这个。可以帮我写吗,好吗?
  • @Strawberry 我使用的是 15.1 版
  • @Strawberry 哦,那个版本的 MariaDB :))。我用的是 7.3.6

标签: php mysql sql


【解决方案1】:

由于关卡的最大深度为 3,我们可以利用两个 self-Join 来确定父 id,并使用自定义 Ordering。

如果您的 MySQL/MariaDB 版本不支持递归 CTE,请尝试以下解决方案:

架构 (MySQL v5.7)

CREATE TABLE comment
    (`id` int, `title` varchar(33), `parent_id` varchar(4))
;

INSERT INTO comment
    (`id`, `title`, `parent_id`)
VALUES
    (1, 'where are you?', NULL),
    (2, 'what is time in your country?', NULL),
    (3, 'im at home', '1'),
    (4, 'its 3 pm', '2'),
    (5, 'oh thats cool', '4')
;

查询 #1

SELECT c1.id, c1.title, c1.parent_id 
FROM comment AS c1 
LEFT JOIN comment AS c2 ON c2.id = c1.parent_id 
LEFT JOIN comment AS c3 ON c3.id = c2.parent_id 
ORDER BY 
  CASE WHEN c1.parent_id IS NULL THEN c1.id  /* first level comment*/
       WHEN c2.parent_id IS NULL THEN c2.id  /* second level comment */
       ELSE c3.id /* comment is at third level */
  END ASC, 
  c1.id ASC;

| id  | title                         | parent_id |
| --- | ----------------------------- | --------- |
| 1   | where are you?                |           |
| 3   | im at home                    | 1         |
| 2   | what is time in your country? |           |
| 4   | its 3 pm                      | 2         |
| 5   | oh thats cool                 | 4         |

View on DB Fiddle

【讨论】:

    【解决方案2】:

    您可以创建递归函数/方法,它将为您执行此循环。或者使用do-while构造:

    $parentIds = null;
    do {
        $where = (is_null($parentIds)) ? 'IS NULL' : sprintf('IN (%s)', implode(',', $parentIds));
    
        $query = $this->db->query("SELECT title FROM comment WHERE parent_id " . $where);
    
        // Do something with $query data
        // In your process $query loop you must fill $parentIds with `parent_id` column value
    
        // ...
        $parentIds[] = $row['parent_id'];
        // ...
    } while (!empty($parentIds));
    

    【讨论】:

      【解决方案3】:
      SELECT c1.title AS lev1, c2.title as lev2, c3.title as lev3
      FROM comment AS C1
      LEFT JOIN category AS c2 ON c2.parent_id = c1.id
      LEFT JOIN category AS c3 ON c3.parent_id = c2.id
      WHERE c1.parent_id IS NULL;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-15
        • 1970-01-01
        • 1970-01-01
        • 2015-03-16
        • 2011-05-03
        • 2015-10-29
        • 1970-01-01
        • 2011-05-20
        相关资源
        最近更新 更多