Php 如何获取以多行值连接的id记录

Php 如何获取以多行值连接的id记录,php,mysql,sql,wordpress,recursive-query,Php,Mysql,Sql,Wordpress,Recursive Query,下面是我的桌子 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

下面是我的桌子

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 
我想输出一个评论回复结构,可以用一个例子来描述。在上表中,您可以看到用户_id 1在833上发表评论这是一个帖子id a post,然后用户168回复他,然后再次用户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')");
?>

让我们首先了解如何加载原始数据:

select Id, content, item_id, secondary_item_id
from table_one
where item_id = 833
order by item_id, secondary_item_id;
上面的查询加载833帖子上的评论,并根据帖子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" => []
        ]
    }
}
现在,您有了一个元素层次结构,主要级别是主注释,您可以在子项中找到答案。现在可以像下面这样遍历分层数组

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;
}

如果您运行的是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\u item\u id=item\u id标识的注释。然后,递归部分只遵循关系,直到它们耗尽

这将为您提供一个平面结构,列出所有评论的帖子,并添加一个名为lvl的列,指示每个元素的深度。您可以使用该信息处理应用程序中的显示

:


您可以使用下面的代码来获取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

实际上,Lajos Arpad的解决方案可以在db中进行一些更改。 添加另一列parent\u item\u id。它基本上是该注释链的第一条注释。在您的示例中,所有3行的值都是879

现在这可以用了

select * from <table name> 
where item_id = <item_id> 
group by parent_item_id 
order by secondary_item_id asc

您有item_id和secondary_item_id。我建议将其更新为父线程或正在讨论的主线程,以及回复到的注释。最后,添加一个时间戳,它使排序变得更好。至于SQL,我会把它推到更容易编码的地方,只需要获取数据。对于层次数据,最好使用嵌套集模型。请参见“未获取结果”,它显示了我在问题中提到的项目\u id 833未获取结果的所有注释,结果必须在层次结构注释结构中。@SamirSheikh:SQL查询按设计返回平面结构行不能嵌套。此查询按从根到子节点的正确顺序提供注释,并有一列指示每个节点的深度。这是SQL查询所能达到的最佳效果。从这些结果开始,很容易使用php循环并使用lvl列在应用程序中将行显示为层次结构。同样,请记住,使用一个查询比在php中迭代并运行多个查询要高效得多。@PaulSpiegel:我明白你的意思。根据OP的需求,有一些解决方案。例如,我们可以跟踪每个注释的路径,并使用if进行排序。但是OP的示例数据并没有显示这个用例,所以我并没有实现它。
select * from <table name> 
where item_id = <item_id> 
group by parent_item_id 
order by secondary_item_id asc