PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

PostgreSQL onde tudo em array


Supondo que a tabela de junção siga as boas práticas e tenha uma chave composta exclusiva definida, ou seja, uma restrição para evitar linhas duplicadas, algo como a consulta simples a seguir deve funcionar.
select conversation_id from conversations_users where user_id in (1, 2)
group by conversation_id having count(*) = 2

É importante observar que o número 2 no final é o comprimento da lista de user_ids. Isso obviamente precisa mudar se a lista user_id mudar de tamanho. Se você não pode presumir que sua tabela de junção não contém duplicatas, altere "count(*)" para "count(distinct user_id)" com algum possível custo no desempenho.

Esta consulta encontra todas as conversas que incluem todos os usuários especificados mesmo que a conversa também inclui usuários adicionais.

Se você deseja apenas conversas com exatamente o conjunto especificado de usuários, uma abordagem é usar uma subconsulta aninhada na cláusula where como abaixo. Observe que a primeira e a última linhas são as mesmas da consulta original, apenas as duas linhas do meio são novas.
select conversation_id from conversations_users where user_id in (1, 2)
   and conversation_id not in
   (select conversation_id from conversations_users where user_id not in (1,2))
group by conversation_id having count(*) = 2

De forma equivalente, você pode usar um operador de diferença de conjunto se seu banco de dados o suportar. Aqui está um exemplo na sintaxe do Oracle. (Para Postgres ou DB2, altere a palavra-chave "minus" para "except.)
select conversation_id from conversations_users where user_id in (1, 2)
  group by conversation_id having count(*) = 2
minus
  select conversation_id from conversations_users where user_id not in (1,2)

Um bom otimizador de consulta deve trate as duas últimas variações de forma idêntica, mas verifique com seu banco de dados específico para ter certeza. Por exemplo, o plano de consulta do Oracle 11GR2 classifica os dois conjuntos de IDs de conversa antes de aplicar o operador menos, mas ignora a etapa de classificação da última consulta. Portanto, qualquer plano de consulta pode ser mais rápido dependendo de vários fatores, como número de linhas, núcleos, cache, índices etc.