简体   繁体   中英

select comments with three levels

I have table that stores the comments . the comments have different deep levels and They have a relationship with each other in one table with id and parent_id . the maximum of the deep level is three and i want select them with one query not with three query and use the foreach three times.

the comment table :

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

the first level is the comments which have parent_id = NULL I use these query to fetch them :

$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))");

is there any way to fetch them with one query?

You can create recursive function/method, which will do this loops for you. Or use do-while construction:

$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));
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;

Since the maximum deepness of the levels is 3, we can utilize two self-Joins to determine the parent id(s), and use custom Ordering.

Try the following solution, in case your MySQL/MariaDB version does not support recursive CTEs:

Schema (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')
;

Query #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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM