mySQL 查询中的条件限制可能吗?

发布于 2024-08-13 19:11:15 字数 614 浏览 2 评论 0原文

我面临着关于在我们的项目中处理线程评论的决定...... 我有一个简单的 MySQL 表,其中包含所有评论。有两种类型:父母和孩子。孩子代表对父母或另一个孩子的答复。

我的问题:

-评论(深度0)
-- 回复子项(深度1)
--- 回复上一个孩子(深度2)
-Comment (深度 0)

想象一下上面的结构和一个 LIMIT 2 的 MySQL 查询。它将剪切最后一个回复 (深度 2)。实际上我想说的是:尝试限制为 2,如果孩子离开,继续直到下一个父母。尝试了几个查询但没有运气...

我现在所拥有的如下:
选择 SQL_CALC_FOUND_ROWS * 从 评论 在哪里 comment_post_id = '{$_REQUEST["ID"]}' 订购依据 评论 ID、评论日期 DESC LIMIT 10"

重要的表字段是:
comment_id(索引)| comment_parent_id(包含父级的comment_id或NULL)| comment_date

我将非常感谢任何想法!

致敬, 布什

i am faced with a decicion regarding handling threaded comments in our project...
I have a simple MySQL table which holds all the comments. There are two types: parents and childs. Childs represent a reply to a parent or another child.

My problem:

-Comment (depth 0)
-- Reply Child (depth 1)
--- Reply to previous child (depth 2)
-Comment (depth 0)

Imagine the above structure and a MySQL query with LIMIT 2. It would cut of the last reply (depth 2). Actually i would like to say something like: Try to limit to 2, if child left go on until the next parent. Tried several queries with no luck...

What i have right now is as followed:
SELECT
SQL_CALC_FOUND_ROWS
*
FROM
comments
WHERE
comment_post_id = '{$_REQUEST["ID"]}'
ORDER BY
comment_id, comment_date
DESC LIMIT 10"

The important table fields are:
comment_id (index) | comment_parent_id (contains comment_id of parent or NULL)| comment_date

I would be very thankful for any ideas!!!

Saludos,
Booosh

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

慢慢从新开始 2024-08-20 19:11:15

我也面临着同样的问题,只是我只深入了一层。

--Comment (depth: 0)
---Reply  (depth: 1)

我设法使用单个查询来选择所有这些记录,同时将顶级 Comment 记录限制为仅 10 条。

SELECT c.* FROM comments AS c WHERE c.OwnerId = 1 AND c.ParentId = 0 LIMIT 10
UNION
SELECT cc.* FROM comments AS cc
    INNER JOIN
    (
        SELECT CommentId FROM comments WHERE OwnerId = 1 AND ParentId = 0 LIMIT 10
    )
    AS c2
    ON cc.ParentId = c2.CommentId

该查询基本上执行以下操作:

  • 获取作为顶级评论的前 10 条记录,并且有一个
    具体所有者 ID。
  • 获取父 id 等于该评论 id 的所有评论
    由第一个查询返回,并将它们联合到结果集。

虽然我认为这个查询比为每条记录多次调用数据库更有效,但它仍然存在执行第一个查询两次的缺陷。一次在工会之前,一次在加入工会时。

它似乎确实相当快,但没有我想要的那么快。但是,如果您的数据库是远程的,并且延迟是一个问题,那么此解决方案可能比对数据库进行多个远程查询更适合您。

I was faced with this same problem, only I was going only one depth deep.

--Comment (depth: 0)
---Reply  (depth: 1)

I managed to use a single query to select all these records, while limiting the top level Comment records to only 10.

SELECT c.* FROM comments AS c WHERE c.OwnerId = 1 AND c.ParentId = 0 LIMIT 10
UNION
SELECT cc.* FROM comments AS cc
    INNER JOIN
    (
        SELECT CommentId FROM comments WHERE OwnerId = 1 AND ParentId = 0 LIMIT 10
    )
    AS c2
    ON cc.ParentId = c2.CommentId

This query basically does the following:

  • Gets the first 10 records that are top level comments, and have a
    specific owner id.
  • Gets all comments that have a parent id equal to the comment id that
    was returned by the first query, and unions them to the result set.

While, I think this query would be more efficient than making multiple calls to the database for each record, it still does have the flaw that it executes the first query twice. Once before the union, and one in the join on the union.

It does seem to be fairly quick, but not as quick as I would like. However, if your database is remote, and latency is an issue, this solution might serve you better than making multiple remote queries to the database.

余罪 2024-08-20 19:11:15

MySQL 没有任何解析树状结构的函数。在最简单的情况下(子节点具有父节点的 ID),您需要以编程方式递归到树中以找到给定节点的所有子节点。 MaxLevel 表示您想要到达的深度。它随着每次递归调用而递减,因此最后得到 0,从而停止递归。

例如(伪代码)

findNodes(String parentId, int maxLevel)
{
  select * from posts where parent = parentId
  foreach (result...)
  {
    if (maxLevel > 0) 
    {
      findNodes(result.nodeId, maxLevel - 1)
    }
    doSomethingWIthAResult
  }
}

为了以更简洁的方式做到这一点,有多种技术,所有这些技术都涉及某种包含当前帖子路径的索引字段。该路径可能看起来像这样: TopNode:Child1:Child2:Child3... 您可以在其中进行这样的选择
从路径如“TopNode%”且深度 = 2 的帖子中选择 *。

MySQL does not have any functions to parse tree-like structures. In the simplest scenario (child has an ID of the parent), you will need to programatically recurse into the tree to locate all the sub-nodes of a given node. MaxLevel indicates the depth you want to go to. It decrements with each recursive call so that at the end you end up with 0, which stops recursion.

e.g. (pseudo-code)

findNodes(String parentId, int maxLevel)
{
  select * from posts where parent = parentId
  foreach (result...)
  {
    if (maxLevel > 0) 
    {
      findNodes(result.nodeId, maxLevel - 1)
    }
    doSomethingWIthAResult
  }
}

To do this in a more concise way, there are a number of techniques, all of which involve some sort of index field that contains path to the current post. The path could look something like this: TopNode:Child1:Child2:Child3... In which you could do a select like this
Select * from posts where path like "TopNode%" and depth = 2.

屋顶上的小猫咪 2024-08-20 19:11:15

始终考虑您真正想要向数据库询问的问题,然后将其转换为 SQL - 在本例中,您需要“所有顶级注释及其直接子级注释的列表(如果有)”。

例如。 (简化)

SELECT * FROM comments c1
LEFT JOIN comments c2 ON c2.parent_comment_id=c1.comment_id
WHERE c1.parent_comment_id IS NULL
ORDER BY c1.comment_date, c1.comment_id, c2.comment_date, c2.comment_id;

有了这个结果,您可以按正确的顺序写出它们 - 如果 c2.comment_id 为 null,则它是没有子级的顶级评论,如果 c1.comment_id 重复,则它是同一评论的另一个子级。

Always think about the question you really want to ask the database and then translate that into SQL - in this case you want "a list of all top-level comments with their immediate children, if any".

eg. (simplified)

SELECT * FROM comments c1
LEFT JOIN comments c2 ON c2.parent_comment_id=c1.comment_id
WHERE c1.parent_comment_id IS NULL
ORDER BY c1.comment_date, c1.comment_id, c2.comment_date, c2.comment_id;

With that result, you can write them out in the right order - if c2.comment_id is null, it's a top-level comment with no children, and if c1.comment_id is repeated, it's another child of the same comment.

北城孤痞 2024-08-20 19:11:15

我终于成功了基于 Greg Adamskis 提示...所以不要投票我的答案,但检查他的答案!

简而言之,我们需要对网站上的评论列表进行分页。使用标准限制可能会导致某些评论永远不会显示...我们需要的是一个限制,它只影响我们的父节点而不是回复的 cild 节点...长话短说...但是也许有一次这个 i 很有用对于某人:

    function getComments($comment_parent_id, $scope,&$comments, $db)
    {
        $res = $db->select("SELECT * FROM comments WHERE comment_post_id = '{$_REQUEST["ID"]}' AND comment_parent_id = '{$comment_parent_id}' ORDER BY comment_date DESC LIMIT {$scope}");

        while ($row = mysql_fetch_array($res, MYSQL_ASSOC)) 
        {
            $i = count($comments)+1;

            foreach ($row as $k => $v) {
                $comments[$i][$k] = $v;
            }

            //LOOK FOR REPLIES (childs of parent)
            if (mysql_num_rows($db->select("SELECT * FROM comments WHERE comment_parent_id = '{$row['comment_id']}' LIMIT 1")) != 0 ){
                getComments($row['comment_id'],100,$comments,$db);
            }
        }
    }

    //ARGUMENTS: parent_id (always starting with zero), scope, array holding comments, db class
    getComments(0,5,$comments,$db);

I finally managed it based on Greg Adamskis hint... So dont vote my answer but check his one!!!

To describe the problem in short... We need a pagination for a comment list on our website. Using a standard limit could cause that some comments never would be shown... What we needed was a Limit which only affected our parent nodes not the cild nodes which are replies... Long story... however maybe one time this iis useful for someone:

    function getComments($comment_parent_id, $scope,&$comments, $db)
    {
        $res = $db->select("SELECT * FROM comments WHERE comment_post_id = '{$_REQUEST["ID"]}' AND comment_parent_id = '{$comment_parent_id}' ORDER BY comment_date DESC LIMIT {$scope}");

        while ($row = mysql_fetch_array($res, MYSQL_ASSOC)) 
        {
            $i = count($comments)+1;

            foreach ($row as $k => $v) {
                $comments[$i][$k] = $v;
            }

            //LOOK FOR REPLIES (childs of parent)
            if (mysql_num_rows($db->select("SELECT * FROM comments WHERE comment_parent_id = '{$row['comment_id']}' LIMIT 1")) != 0 ){
                getComments($row['comment_id'],100,$comments,$db);
            }
        }
    }

    //ARGUMENTS: parent_id (always starting with zero), scope, array holding comments, db class
    getComments(0,5,$comments,$db);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文