如何获取以多行值连接的 id 记录
Posted
技术标签:
【中文标题】如何获取以多行值连接的 id 记录【英文标题】:How can i get records of id those are connected in multiple row value 【发布时间】:2020-08-09 09:41:54 【问题描述】:下面是我的桌子
Id User_id type content item_id secondary_item_id
879 1 activity_comment Amazing 833 833
907 168 activity_comment Great 833 879
908 1 activity_comment Welcome 833 907
我想输出一个评论回复结构,可以用一个例子来描述。在上表中,您可以看到 user_id 1
对 833 ( this is a post id )
发表评论,然后 user 168
回复他为“很棒”,然后再次 user 1
重播给用户 168。
所以它可能像......
**MY POST** ( This is a post )
---- First comment( Amazing)
------- replay comment (Great)
------------ sub replay (Welcome )
我已经编写了以下查询,但无法获得预期的输出。
SQL 查询:
<?php
$listReplay =$wpdb->get_results("(SELECT * FROM table_one WHERE id = ".$value['secondary_item_id']." AND type ='activity_comment') UNION DISTINCT
(SELECT * FROM table_one WHERE secondary_item_id = ".$value['secondary_item_id']." AND type ='activity_comment')");
?>
【问题讨论】:
你有item_id
和secondary_item_id
。我建议将其更新为parent_id
或正在讨论的主线程和replied_to_id
,这将是正在回复的评论。最后,添加一个timestamp
,它会让排序变得更好。至于获得该结构的 SQL,我会推动它以更轻松地对其进行编码,只需获取数据即可。
对于分层数据最好使用嵌套集模型。见phpro.org/tutorials/…
【参考方案1】:
让我们首先了解如何加载原始数据:
select Id, content, item_id, secondary_item_id
from table_one
where item_id = 833
order by item_id, secondary_item_id;
上面的查询加载了帖子 833 上的 cmets,并按帖子 ID 和父评论 ID 对它们进行排序。到目前为止,一切都很好。现在,假设您将原始数据存储在 $rawResults
中,您可以执行以下操作:
$map = [];
$parsedResults = [];
foreach ($rawResults as $rawResult)
if ($rawResult["secondary_item_id"] === $rawResult["item_id"])
$parsedResults[$rawResult["Id"]] = [
"content" => $rawResult["content"],
"children" => []
];
$map[$rawResult["Id"]] = $parsedResults[$rawResults["Id"]];
else
$map[$rawResult["secondary_item_id"]]["children"][$rawResult["Id"]]= [
"content" => $rawResult["content"],
"children" => []
]
现在,您有一个元素层次结构,主要级别是主要 cmets,您可以在子项中找到答案。您现在可以像
一样遍历分层数组function getComments($parsedResults, $prefix = "--- ")
$output = "";
foreach ($parsedResults as $parsedResult)
$output .= $prefix.$parsedResult["content"]."\n";
if (count($parsedResult["children"])) $output .= getComments($parsedResult["children"], "---".$prefix);
return $output;
【讨论】:
【参考方案2】:如果您运行的是 mysql 8.0,一个典型的方法是使用递归查询来遍历分层数据结构。这会通过单个查询产生所需的结果,因此这比在 php 中迭代更有效。
with recursive cte as (
select t.*, 1 lvl
from mytable t
where
type ='activity_comment'
and item_id = 833
and secondary_item_id = item_id
union all
select t.*, c.lvl + 1
from mytable t
inner join cte c on c.id = t.secondary_item_id
where t.type = 'activity_comment'
)
select * from cte order by lvl
递归查询的锚点选择帖子的“第一个”评论,即我们用条件secondary_item_id = item_id
识别。然后,递归部分只是跟随关系直到它们耗尽。
这为您提供了一个列出所有评论帖子的扁平结构,并带有一个名为 lvl
的附加列,指示每个元素的深度。您可以使用该信息来处理应用程序中的显示。
Demo on DB Fiddle:
身份证 |用户ID |类型 |内容 | item_id | secondary_item_id |等级 --: | ------: | :--------------- | :-------- | ------: | ----------------: | --: 第879章1 |活动评论 |惊人的 |第833章第833章1 907 | 168 |活动评论 |很棒 |第833章第879章2 908 | 1 |活动评论 |欢迎 |第833章907 | 3【讨论】:
没有得到结果,它显示了我在问题中提到的item_id 833的所有cmets没有得到结果,结果必须在层次注释结构中。 @SamirSheikh:SQL 查询按设计返回平面结构(行不能“嵌套”)。此查询以正确的顺序(从根到子)为您提供 cmets,并有一列指示每个节点的深度。这与 SQL 查询一样好。从这些结果开始,很容易使用 php 循环并使用lvl
列将行显示为应用程序中的层次结构。而且,再次记住,使用单个查询比在 php 中迭代和运行多个查询要高效得多。
@PaulSpiegel:我明白你的意思。有解决方案 - 取决于 OP 想要什么。例如,我们可以跟踪每个评论的路径,并使用 if 进行排序。但是 OP 的示例数据没有显示这个用例,所以我没有实现。【参考方案3】:
您可以使用以下代码在 SQL 中获取输出。
WITH comment_activity(Id, User_id, type, content, post_id, secondary_item_id)
AS
(Select 879 , 1 , 'activity_comment' , 'Amazing' , 833 , 833 UNION
Select 907 , 168 , 'activity_comment' , 'Great' , 833 , 879 UNION
Select 908 , 1 , 'activity_comment' , 'Welcome' , 833 , 907
)
Select post_id as post,
ROW_NUMBER() OVER (PARTITION BY post_id ORDER BY ID) as RN,
content as comment,
User_id,
CASE WHEN ROW_NUMBER() OVER (PARTITION BY post_id ORDER BY ID) = 1
THEN 'First_Comment (' + content + ')'
ELSE 'Reply_' + CONVERT(VARCHAR(20),ROW_NUMBER() OVER (PARTITION BY post_id ORDER BY ID) - 1) + '( ' + content + ')'
END as Thread
from comment_activity
WHERE type = 'activity_comment'
AND post_id = 833
【讨论】:
【参考方案4】:实际上,Lajos Arpad 的解决方案可以在数据库中进行一些更改。 您添加另一列 parent_item_id。这基本上是该链 cmets 的第一个评论。在您的示例中,所有 3 行都是 879。
现在这可以工作了
select * from <table name>
where item_id = <item_id>
group by parent_item_id
order by secondary_item_id asc
【讨论】:
以上是关于如何获取以多行值连接的 id 记录的主要内容,如果未能解决你的问题,请参考以下文章