문제

기사에 대한 의견을 저장하는 CMS가 있습니다. 이 의견은 나사산과 스레드가 아닌 것일 수 있습니다. 기술적으로는 회신 열이 나사산되지 않았을 때 비워 두는 것과 동일합니다. 내 응용 프로그램은 sqllite, mysql 및 pgsql에서 작동하므로 상당히 표준 SQL이 필요합니다.

현재 의견 테이블이 있습니다

comment_id
article_id
user_id
comment
timestamp
thread (this is the reply column)

내 질문은 데이터베이스에서 스레드 주석을 가장 잘 표현하는 방법을 알아내는 것입니다. 아마도 내용없이 트리 세트를 지원하는 별도의 테이블과 텍스트를 보유 할 간단한 테이블? 아마도 이미 그 방식에 따라? 아마도 다른 방법?

주석이 스레드되지 않은 경우 타임 스탬프로 쉽게 주문할 수 있습니다.

그들이 실로 된 경우 나는 이것처럼 정렬합니다

ORDER BY SUBSTRING(c.thread, 1, (LENGTH(c.thread) - 1))

주문에서 볼 수 있듯이 주석 쿼리는 인덱스를 기능 기반 색인으로 사용하지 않습니다. 빠른 댓글 페이지를 밝히도록 도와주세요.

도움이 되었습니까?

해결책

나는 정말 좋아한다 드 루팔 이 문제를 해결합니다. 각 주석에 스레드 ID를 할당합니다. 이 ID는 첫 번째 주석을 위해 1에서 시작합니다. 이 주석에 답장이 추가되면 ID 1.1 그것에 할당됩니다. 의견에 대한 답변 1.1 스레드 ID가 주어집니다 1.1.1. 의견의 형제 1.1 스레드 ID가 주어집니다 1.2. 당신은 아이디어를 얻습니다. 주석이 추가되면 하나의 쿼리로 이러한 스레드 ID를 쉽게 수행 할 수 있습니다.

스레드가 렌더링되면 스레드에 속하는 모든 주석이 스레드 ID로 정렬 된 단일 쿼리로 가져옵니다. 이것은 당신에게 오름차순 순서로 스레드를 제공합니다. 또한 스레드 ID를 사용하여 각 주석의 중첩 레벨을 찾아서 그에 따라 들여 줄 수 있습니다.

1
1.1
1.1.1
1.2
1.2.1

정리해야 할 몇 가지 문제가 있습니다.

  • 스레드 ID의 한 구성 요소가 2 자리로 증가하면 스레드 ID로 정렬하면 예상 순서가 생성되지 않습니다. 쉬운 솔루션은 스레드 ID의 모든 구성 요소가 0에 의해 동일한 너비를 갖도록 패딩하는 것입니다.
  • 하강 스레드 ID로 정렬해도 예상 하강 순서가 생성되지 않습니다.

Drupal은 Vancode라는 번호 시스템을 사용하여보다 복잡한 방식으로 첫 번째 문제를 해결합니다. 두 번째 문제의 경우, 순서를 내려 놓을 때 BackSlash (ASCII 코드가 숫자보다 높은)를 스레드 ID에 추가하여 해결됩니다. 이 구현에 대한 자세한 내용은 주석 모듈 (COMMENT_GET_THREAD 함수 전에 큰 주석을 참조하십시오).

다른 팁

답이 조금 늦었다는 것을 알고 있지만 나무 데이터의 경우 폐쇄 테이블을 사용하십시오.http://www.slideshare.net/billkarwin/models-for-hierarchical-data

4 가지 방법을 설명합니다.

  • 조정 목록 (간단한 부모 외국 키)
  • 경로 열거 (허용 답변에 언급 된 드 루팔 전략)
  • 중첩 된 세트
  • 클로저 테이블 (조상/후손 사실을 별도의 관계에 저장 [표], 가능한 거리 열이있는)

마지막 옵션은 나머지와 비교하여 쉬운 크루드 작업의 장점이 있습니다. 비용은 최악의 경우 수 트리 노드에서 O (n^2) 크기 인 공간이지만 실제로는 그렇게 나쁘지 않을 것입니다.

불행히도, 순수한 SQL 방법은 매우 느립니다.

그만큼 NESTED SETS 에 의해 제안 @Marc W 매우 우아하지만 나무 가지가 범위에 닿으면 트리 전체를 업데이트해야 할 수도 있습니다.

내 블로그에서 빠르게 수행하는 방법에 대한이 기사를 참조하십시오. MySQL:

함수를 만들어야합니다.

CREATE FUNCTION hierarchy_connect_by_parent_eq_prior_id(value INT) RETURNS INT
NOT DETERMINISTIC
READS SQL DATA
BEGIN
        DECLARE _id INT;
        DECLARE _parent INT;
        DECLARE _next INT;
        DECLARE CONTINUE HANDLER FOR NOT FOUND SET @id = NULL;

        SET _parent = @id;
        SET _id = -1;

        IF @id IS NULL THEN
                RETURN NULL;
        END IF;

        LOOP
                SELECT  MIN(id)
                INTO    @id
                FROM    t_hierarchy
                WHERE   parent = _parent
                        AND id > _id;
                IF @id IS NOT NULL OR _parent = @start_with THEN
                        SET @level = @level + 1;
                        RETURN @id;
                END IF;
                SET @level := @level - 1;
                SELECT  id, parent
                INTO    _id, _parent
                FROM    t_hierarchy
                WHERE   id = _parent;
        END LOOP;
END

다음과 같은 쿼리에 사용하십시오.

SELECT  hi.*
FROM    (
        SELECT  hierarchy_connect_by_parent_eq_prior_id(id) AS id, @level AS level
        FROM    (
                SELECT  @start_with := 0,
                        @id := @start_with,
                        @level := 0
                ) vars, t_hierarchy
        WHERE   @id IS NOT NULL
        ) ho
JOIN    t_hierarchy hi
ON      hi.id = ho.id

이것은 물론입니다 MySQL 구체적이지만 정말 빠릅니다.

당신이 이것을 휴대용 베트 웬이되기를 원한다면 PostgreSQL 그리고 MySQL, 당신이 사용할 수있는 PostgreSQL의 기여 CONNECT BY 쿼리를 두 시스템에 대해 동일한 이름으로 저장된 절차로 랩합니다.

나는 실제로 이것을 직접했다! 관계형 데이터베이스에서 계층 적 데이터를 나타내는 중첩 세트 모델을 사용했습니다.

MySQL에서 계층 적 데이터 관리 나에게 순수한 금이었다. 중첩 세트는 해당 기사에 설명 된 두 번째 모델입니다.

인접성과 중첩 세트 모델 중에서 선택할 수 있습니다. 기사 MySQL에서 계층 적 데이터 관리 좋은 소개를합니다.

이론적 논의는 Celko 's를 참조하십시오 나무와 계층.

데이터베이스가 윈도우 기능을 지원하는 경우 스레드 목록을 구현하기가 쉽습니다. 대상 데이터베이스 테이블의 재귀 참조 만 있으면됩니다.

create Tablename (
  RecordID integer not null default 0 auto_increment,
  ParentID integer default null references RecordID,
  ...
)

그런 다음 재귀 공통 테이블 표현식을 사용하여 나사산보기를 표시 할 수 있습니다. 예를 사용할 수 있습니다 여기.

실제로 읽기와 쓰기 사이의 균형이어야합니다.

모든 인서트에 많은 행을 업데이트해도 괜찮다면 중첩 된 세트 (또는 이와 동등한)는 쉽고 빠른 읽기를 제공합니다.

그 외에도 부모의 간단한 FK는 초강력 삽입물을 제공하지만 검색의 악몽 일 수 있습니다.

나는 중첩 된 세트와 함께 갈 것이라고 생각하지만 예상되는 데이터 볼륨 및 사용 패턴에주의를 기울여야합니다 (모든 인덱스 열에있는 두 개의 색인화 된 열 (왼쪽 및 오른쪽 정보)의 여러 행을 업데이트하면 문제가 될 수 있습니다. 어느 시점에서).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top