Pergunta

i sou confrontado com uma decicion sobre manipulação de comentários de rosca em nosso projeto ... Eu tenho uma tabela MySQL simples que detém todos os comentários. Existem dois tipos: os pais e da criança. Childs representam uma resposta a um pai ou outra criança.

Meu problema:

-Comment (profundidade 0)
- Responder Criança (profundidade 1)
--- Responder a criança anterior (profundidade 2)
-Comment (profundidade 0)

Imagine a estrutura acima e uma consulta MySQL com LIMIT 2. Seria cortado da última resposta (profundidade 2). Na verdade eu gostaria de dizer algo como: tentar limitar a 2, se a criança deixou ir até o próximo pai. Tentou várias consultas sem sorte ...

O que eu tenho agora é como se segue:
SELECIONAR SQL_CALC_FOUND_ROWS * DE comentários ONDE comment_post_ID = '{$ _REQUEST [ "ID"]}' ORDENAR POR comment_id, COMMENT_DATE DESC LIMIT 10"

Os campos da tabela importantes são:
comment_id (índice) | comment_parent_id (contém comment_id de pai ou NULL) | COMMENT_DATE

Eu ficaria muito grato por todas as idéias !!!

Saludos, Booosh

Foi útil?

Solução

MySQL não tem quaisquer funções para analisar árvore-como estruturas. No cenário mais simples (criança tem um ID do pai), você precisará recurse através de programação para a árvore para localizar todos os sub-nós de um determinado nó. MaxLevel indica a profundidade que você quer ir para. Ele diminui a cada chamada recursiva para que no final você acaba com 0, que pára a recursão.

por exemplo. (Pseudo-código)

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

Para fazer isso de uma forma mais concisa, há uma série de técnicas, todas as quais envolvem algum tipo de campo de índice que contém caminho para o posto atual. O caminho pode ser algo como isto: TopNode: Child1: Criança2: Filho3 ... Em que você poderia fazer uma escolha como essa Selecione * de mensagens em que caminho como "TopNode%" e profundidade = 2.

Outras dicas

Sempre penso sobre a pergunta que você realmente quer pedir ao banco de dados e então traduzir isso em SQL - neste caso você quer "uma lista de todos os comentários de alto nível com os seus filhos imediatos, se houver ".

por exemplo. (Simplificado)

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;

Com esse resultado, você pode escrevê-los na ordem certa - se c2.comment_id é nulo, é um comentário de nível superior sem filhos, e se c1.comment_id é repetido, é uma outra criança do mesmo comentário.

fui confrontado com este mesmo problema, só que eu estava indo apenas uma profundidade de profundidade.

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

Eu consegui usar uma única consulta para selecionar todos esses registros, enquanto limita os registros Comment nível superior para apenas 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

Esta consulta faz basicamente o seguinte:

  • Obtém os 10 primeiros registros que são comentários de alto nível, e têm um específica id proprietário.
  • Obtém todos os comentários que têm um ID de pai igual ao comentário id que foi devolvido pela primeira consulta, e os sindicatos los para o conjunto de resultados.

Embora, eu acho que essa consulta seria mais eficiente do que fazer várias chamadas para o banco de dados para cada registro, ele ainda tem a falha que ele executa a primeira consulta duas vezes. Uma vez antes da união, e um na juntar-se à União.

Ele parece ser bastante rápido, mas não tão rápido como eu gostaria. No entanto, se seu banco de dados é remoto, e latência é um problema, esta solução pode servi-lo melhor do que fazer várias consultas remotas ao banco de dados.

Eu finalmente consegui-lo com base em Greg Adamskis dica ... Então não vote a minha resposta, mas verificar a sua única !!!

Para descrever o problema em curto ... Precisamos de uma paginação para uma lista de comentários em nosso site. Usando um limite padrão pode causar que alguns comentários não seria mostrado ... O que precisávamos era um limite que só afetou nossas nós pais não os gânglios cild que são respostas ... É uma longa história ... No entanto talvez uma vez este iis útil para alguém:

    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);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top