문제

프로젝트에서 스레드 댓글을 다루는 것에 관한 속임수에 직면하고 있습니다 ... 모든 의견을 담은 간단한 MySQL 테이블이 있습니다. 부모와 자녀의 두 가지 유형이 있습니다. 자녀는 부모 나 다른 자녀에게 답장을 나타냅니다.

내 문제:

-Comment (깊이 0)
- 답장 아이 (깊이 1)
--- 이전 아동에 대한 답장 (깊이 2)
-Comment (깊이 0)

위의 구조와 Limit 2가있는 MySQL 쿼리를 상상해보십시오. 마지막 응답 (깊이 2)이 절단 될 것이라고 상상해보십시오. 실제로 나는 다음과 같은 말을하고 싶습니다 : 아이가 다음 부모가 될 때까지 자녀가 떠나면 2로 제한하십시오. 운이없는 몇 가지 쿼리를 시도했습니다 ...

내가 지금 가지고있는 것은 다음과 같습니다.
comment_post_id = '{$ _request [ "id"]}'order by comment_id, comment_date desc limit 10 "에서 sql_calc_found_rows *를 선택하십시오.

중요한 테이블 필드는 다음과 같습니다.
comment_id (인덱스) | comment_parent_id (parent or 또는 null의 comment_id 포함) | 댓글_DATE

나는 어떤 아이디어라도 매우 감사 할 것입니다 !!!

샐러도스, 부리

도움이 되었습니까?

해결책

MySQL에는 트리와 같은 구조를 구문 분석하는 기능이 없습니다. 가장 간단한 시나리오 (자식은 부모의 ID가 있음)에서 주어진 노드의 모든 하위 노드를 찾기 위해 트리에 프로그래밍 방식으로 재발해야합니다. Maxlevel은 가고 싶은 깊이를 나타냅니다. 마지막으로 재귀 호출마다 감소하여 마지막에 0으로 끝나면 재귀를 멈 춥니 다.

EG (의사 코드)

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와 같은 경로 에서이 선택 *과 같이 선택을 할 수 있습니다.

다른 팁

항상 데이터베이스를 요청하고 싶은 질문에 대해 생각하고 그 다음에 이를 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;

그 결과로 올바른 순서로 작성할 수 있습니다.

나는이 같은 문제에 직면했다.

--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와 동일한 모든 주석을 가져오고 결과 세트로 연결됩니다.

이 쿼리는 각 레코드에 대해 데이터베이스를 여러 호출하는 것보다 더 효율적이라고 생각하지만 여전히 첫 번째 쿼리를 두 번 실행한다는 결함이 있습니다. 한 번은 노조하기 전에, 그리고 노조에 가입 한 사람.

상당히 빠르지 만 내가 원하는만큼 빠르지는 않습니다. 그러나 데이터베이스가 원격이고 대기 시간이 문제가되는 경우이 솔루션은 데이터베이스에 여러 원격 쿼리를 만드는 것보다 더 나은 서비스를 제공 할 수 있습니다.

나는 마침내 그것을 관리했다 Greg Adamskis 힌트를 기반으로합니다... 그러니 내 대답에 투표하지 말고 그의 대답을 확인하십시오 !!!

짧은 문제를 설명하려면 ... 웹 사이트의 의견 목록에 대한 페이지 매김이 필요합니다. 표준 제한을 사용하면 일부 의견이 표시되지 않을 수 있습니다 ... 우리가 필요로하는 것은 답장 인 Cild 노드가 아닌 부모 노드에만 영향을 미치는 한계였습니다 ... 긴 이야기 ... 그러나 아마도이 IIS 유용한 일 수도 있습니다. 누군가를 위해 :

    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);
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top