2012/12/6 Thiago <zan...@farmaponte.com.br> > On 05/12/2012 17:16, Matheus de Oliveira wrote: > > > > > > 2012/12/5 Thiago <zan...@farmaponte.com.br > > <mailto:zan...@farmaponte.com.br>> > > > > Boa tarde. > > > > Tenho as seguintes tabelas: > > > > tb_mensagem > > id > > id_mensagem_pai > > dth_insert > > > > tb_mensagem_leitura > > id_mensagem > > dth_insert > > > > A tabela de mensagens, sempre que existe uma mensagem com > > id_mensagem_pai, significa que é uma resposta, as mensagens originais > > (primeiras) contém 0 (zero) no campo id_mensagem_pai. > > > > Na tabela tb_mensagem_leitura eu tenho um histórico de todas as vezes > > que o usuário leu a mensagem, sendo gravado no campo id_mensagem > dessa > > tabela sempre o id da mensagem original. > > > > Preciso identificar quantas mensagens não lidas existe na para o > > usuário, sendo que uma mensagem não lida é: > > 1) sem registro na tabela tb_mensagem_leitura; > > 2) o registro da tabela tb_mensagem_leitura é com data menor que a > > última resposta da mensagem original. > > > > Alguém poderia me ajudar com este select? Ou até mesmo com a forma em > > que estruturei as tabelas, pois para chegar neste resultado está um > > pouco complicado. > > > > > > Cara, se eu não boiei na maionese, a consulta abaixo resolve o seu > > problema (não testado): > > > > WITH RECURSIVE mensagens AS ( > > SELECT id AS id_original, id, dth_insert > > FROM tb_mensagem > > WHERE id_mensagem_pai = 0 > > UNION ALL > > SELECT pai.id_original, filha.id <http://filha.id>, > filha.dth_insert > > FROM tb_mensagem AS filha > > INNER JOIN mensagens AS pai ON pai.id <http://pai.id> = > > filha.id_mensagem_pai > > ), ultimas AS ( > > SELECT m.id_original, MAX(m.dth_insert) AS dth_insert > > FROM mensagens AS m > > GROUP BY m.id_original > > ) > > SELECT COUNT(*) > > FROM ultimas AS u > > LEFT JOIN tb_mensagem_leitura AS l > > ON l.id_mensagem = u.id_original > > WHERE l.id_mensagem IS NULL OR l.dth_insert < u.dth_insert; > > > > > > Não me parece muito performático, uma forma de melhorar seria SEMPRE > > guardar o id da mensagem original em tb_mensagem (não só a da pai, mas a > > da primeira na hierarquia), o que evitaria toda essa sobrecarga da query > > recursiva e da outra sub-query, que na prática só estão pegando a data > > da última mensagem. > > > > Atenciosamente, > > Mateus, muito obrigado pela resposta. > > Acho que não expliquei direito.
Também acho... =P > Na tabela tb_mensagem, o campo > id_mensagem_pai é sempre o id da mensagem original. Todas as respostas > estão amarradas a uma única mensagem e não em um formato de árvore. > > Agora entendi, é mais simples então. Dessa forma você acha que existe uma solução melhor com uma melhor > performance? Essa será uma leitura muitas vezes executada, pois cada > página do portal que o usuário acessa essa consulta é refeita para > atualizar as mensagens não lidas. > > > Sim. A forma abaixo: SELECT COUNT(*) FROM ( SELECT CASE m.id_mensagem_pai WHEN 0 THEN m.id ELSE m.id_mensagem_pai END AS id_original, MAX(m.dth_insert) AS dth_insert FROM tb_mensagem AS m GROUP BY CASE m.id_mensagem_pai WHEN 0 THEN m.id ELSE m.id_mensagem_pai END ) AS u LEFT JOIN tb_mensagem_leitura AS l ON l.id_mensagem = u.id_original WHERE l.id_mensagem IS NULL OR l.dth_insert < u.dth_insert; Eu modelaria na mensagem original o id_mensagem_pai = id ao invés de 0 na mensagem original, assim tira esse CASE daí. Atenciosamente, -- Matheus de Oliveira Analista de Banco de Dados PostgreSQL Dextra Sistemas - MPS.Br nível F! www.dextra.com.br/postgres
_______________________________________________ pgbr-geral mailing list pgbr-geral@listas.postgresql.org.br https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral