[英]Selecting All Children From All Parents in mySQL
我有一个这样的简单表格:
+------------+---------+-----------+--------------+
| comment_id | post_id | parent_id | comment_text |
+------------+---------+-----------+--------------+
| 1 | 200 | 0 | a |
| 2 | 200 | 0 | b |
| 3 | 200 | 1 | c |
| 4 | 200 | 1 | d |
| 5 | 200 | 0 | e |
| 6 | 200 | 2 | f |
| 7 | 200 | 2 | g |
| 8 | 200 | 0 | h |
| 9 | 200 | 0 | i |
| 10 | 200 | 1 | k |
+------------+---------+-----------+--------------+
列parent_id告诉我们此评论是对此id的另一个评论的回复。
假设只有一个级别的注释嵌套。
现在我只需返回前5条父评论和所有属于它们的孩子。
我有一个查询,但有一个问题。
(
SELECT c.*
FROM comments AS c
WHERE c.post_id = '200' AND parent_id='0'
LIMIT 0,5
)
UNION
(
SELECT c.*
FROM comments AS c
WHERE c.post_id = '200' AND c.parent_id IN
(
SELECT c.comment_id
FROM comments AS c
WHERE c.post_id= '200' AND parent_id='0'
LIMIT 0,5
)
)
问题是我当前的mySQL版本在子查询中不支持LIMIT。 似乎我两次执行相同的SELECT查询!
我敢肯定必须有办法更优雅地做到这一点。
最后,我最终使用了Andomar建议但没有子查询的东西:
(
select *
from comments c
where c.post_id = '200'
and c.parent_id = 0
order by comment_id DESC limit 0, 4
)
union
(
select *
from comments c
join comments p
on c.parent_id = p.comment_id
where c.post_id = '200'
and c.parent_id != '0'
)
order by comment_id DESC
编辑:正如niaher正确指出的那样,这个查询返回的结果集比需要的大得多。 这使得这个解决方案错了。
幸运的是,我找到了另一种方法,更优雅,更清洁。
正确的方法:
SELECT c.*
FROM (
SELECT comment_id
FROM comments
WHERE post_id = 200 AND parent_id = 0
ORDER BY comment_id ASC
LIMIT 0,5
) AS q
JOIN comments AS c
ON c.comment_id = q.comment_id OR c.parent_id = q.comment_id
我已经测试了这个查询,它比前一个查询运行得更快。
这是最优雅的方式: http : //mikehillyer.com/articles/managing-hierarchical-data-in-mysql/ 。 您将遇到的一个问题是,插入需要一些时间,因为其他行需要更新; 然而,这可以通过一些创造力来避免。 那篇文章是一个很好的开始。
你能做2次选择吗?
Select * from comments where parentID = 0 limit 5
select * from comments where parentID IN (*list of the 5 parentIDs)
在我的MySQL版本中,您可以在子查询中使用limit:
select *
from (
select *
from comments c
where c.post_id = '200'
and c.parent_id = 0
limit 0, 3
) s
union
select c.*
from (
select *
from comments c
where c.post_id = '200'
and c.parent_id = 0
limit 0, 3
) p
join comments c
on c.parent_id = p.comment_id;
如果没有MySQL不支持的with
语句,重复选择很难避免。 您可以创建一个临时表来存储它们:
drop table if exists top5comments;
create table top5comments
select *
from comments c
where c.post_id = '200'
and c.parent_id = 0
limit 0, 3;
insert top5comments
select children.*
from top5comments parents
join comments children
on children.parent_id = parents.comment_id;
select * from top5comments;
如果查询可以同时由多个连接运行,则需要进行修改。
PS顺便说一句, limit
声明通常伴随着order by
子句。 如果没有order by
,您将获得任意行,结果可能因查询而异。
也许你的意思是:
SELECT
*,
(CASE WHEN parent_id = 0 THEN comment_id ELSE parent_id END) AS use_id
FROM
comments
WHERE
(CASE WHEN parent_id = 0 THEN comment_id ELSE parent_id END) IN (
SELECT comment_id
FROM comments
WHERE parent_id = 0
ORDER BY comment_id ASC
LIMIT 3)
ORDER BY
use_id ASC,
parent_id;
它的作用是取三个'first'(由comment_id ASC排序)父评论及其所有孩子,然后按parent- / comment_id排序整个列表(父母优先,孩子之后)。
例如,那么ELSE END用于SQLite(这就是我测试这些东西的方式)。
- 编辑
如果存在这些记录(超过10个记录):
comment_id post_id parent_id comment
1 200 0 a
2 200 0 b
3 200 1 c
4 200 1 d
5 200 0 e
6 200 2 f
7 200 2 g
8 200 0 h
9 200 0 i
10 200 1 j
11 200 1 k
12 200 2 l
13 200 0 m
14 200 1 n
这将是结果:
comment_id post_id parent_id comment use_id
1 200 0 a 1
3 200 1 c 1
4 200 1 d 1
10 200 1 j 1
11 200 1 k 1
14 200 1 n 1
2 200 0 b 2
6 200 2 f 2
7 200 2 g 2
12 200 2 l 2
5 200 0 e 5
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.