Reputation: 341
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?
Upvotes: 1
Views: 226
Reputation: 28844
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 |
Upvotes: 1
Reputation: 190
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;
Upvotes: 0
Reputation: 281
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));
Upvotes: 0