Consulta SQL para localizar registros em que contagem> 1


176

Eu tenho uma tabela chamada PAYMENT. Nesta tabela, tenho um ID do usuário, um número de conta, um CEP e uma data. Gostaria de encontrar todos os registros para todos os usuários que têm mais de um pagamento por dia com o mesmo número de conta.

ATUALIZAÇÃO: Além disso, deve haver um filtro que conte apenas os registros cujo CEP é diferente.

É assim que a tabela se parece:

| user_id | account_no | zip | data |
| 1 | 123 55555 12-dez-09
| 1 | 123 66666 12-dez-09
| 1 | 123 55555 13-dez-09
| 2 456 77777 14-dez-09
| 2 456 77777 14-dez-09
| 2 789 77777 14-dez-09
| 2 789 77777 14-dez-09

O resultado deve ser semelhante a este:

| user_id | contar |
| 1 | 2

Como você expressaria isso em uma consulta SQL? Eu estava pensando em participar, mas por algum motivo minha contagem está errada.

Respostas:


344

Use a cláusula HAVING e GROUP By os campos que tornam a linha exclusiva

O abaixo encontrará

todos os usuários que têm mais de um pagamento por dia com o mesmo número de conta

SELECT 
 user_id ,
 COUNT(*) count
FROM 
 PAYMENT
GROUP BY
 account,
 user_id ,
 date
Having
COUNT(*) > 1

Atualizar Se você deseja incluir apenas aqueles que possuem um ZIP distinto, é possível obter um conjunto distinto primeiro e, em seguida, executar

 SELECT 
    user_id,
    account_no , 
    date,
        COUNT(*)
 FROM
    (SELECT DISTINCT
            user_id,
            account_no , 
            zip, 
            date
         FROM
            payment 

        ) 
        payment
 GROUP BY

    user_id,
    account_no , 

    date
HAVING COUNT(*) > 1

1
Observe em seus resultados 2uma contagem de 4- Você vai querer descartar o Account_noagrupamento, eu acho.
JNK

Não, espere, acho que o original estava certo "todos os usuários que têm mais de um pagamento por dia com o mesmo número de conta".
Conrad Frix

diz isso, mas seus resultados mostram o contrário. Talvez tenha as duas versões com uma nota.
JNK

Obrigado por suas respostas. Eu acho que deveria fazê-lo. Se agora eu desejasse adicionar outro filtro que verifique se o CEP de cobrança (mesma tabela, coluna diferente) é diferente para a mesma data, como eu modificaria essa consulta?
Benjamin Muschko

Não consigo resolver a saída de amostra. Se abandonarmos a conta, teremos três linhas. Se abandonarmos a data e a conta, teremos duas linhas 1,3 e 2,4. Então, eu estou indo para ir em frente e confiar nas palavras sobre a saída
Conrad Frix

43

Tente esta consulta:

SELECT column_name
  FROM table_name
 GROUP BY column_name
HAVING COUNT(column_name) = 1;

4
arrumado, mas isso não responde à pergunta #
7783

4

Eu não recomendaria a HAVINGpalavra - chave para iniciantes, é essencialmente para fins legados .

Não sei ao certo qual é a chave dessa tabela (ela está totalmente normalizada , eu me pergunto?); Conseqüentemente, acho difícil seguir sua especificação:

Gostaria de encontrar todos os registros de todos os usuários que têm mais de um pagamento por dia com o mesmo número de conta ... Além disso, deve haver um filtro que conte apenas os registros cujo CEP é diferente.

Então, eu fiz uma interpretação literal.

O seguinte é mais detalhado, mas poderia ser mais fácil de entender e, portanto, manter (usei um CTE para a tabela, PAYMENT_TALLIESmas poderia ser um VIEW:

WITH PAYMENT_TALLIES (user_id, zip, tally)
     AS
     (
      SELECT user_id, zip, COUNT(*) AS tally
        FROM PAYMENT
       GROUP 
          BY user_id, zip
     )
SELECT DISTINCT *
  FROM PAYMENT AS P
 WHERE EXISTS (
               SELECT * 
                 FROM PAYMENT_TALLIES AS PT
                WHERE P.user_id = PT.user_id
                      AND PT.tally > 1
              );

2
create table payment(
    user_id int(11),
    account int(11) not null,
    zip int(11) not null,
    dt date not null
);

insert into payment values
(1,123,55555,'2009-12-12'),
(1,123,66666,'2009-12-12'),
(1,123,77777,'2009-12-13'),
(2,456,77777,'2009-12-14'),
(2,456,77777,'2009-12-14'),
(2,789,77777,'2009-12-14'),
(2,789,77777,'2009-12-14');

select foo.user_id, foo.cnt from
(select user_id,count(account) as cnt, dt from payment group by account, dt) foo
where foo.cnt > 1;
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.