Requête SQL pour rechercher des enregistrements où nombre> 1

177

J'ai une table nommée PAYMENT. Dans ce tableau, j'ai un ID utilisateur, un numéro de compte, un code postal et une date. Je souhaite rechercher tous les enregistrements de tous les utilisateurs qui effectuent plus d'un paiement par jour avec le même numéro de compte.

MISE À JOUR: De plus, il devrait y avoir un filtre qui ne compte que les enregistrements dont le code postal est différent.

Voici à quoi ressemble le tableau:

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

Le résultat devrait ressembler à ceci:

| user_id | compte |
| 1 | 2 |

Comment exprimeriez-vous cela dans une requête SQL? Je pensais me rejoindre mais pour une raison quelconque, mon compte est faux.

Benjamin Muschko
la source

Réponses:

346

Utilisez la clause HAVING et GROUP Par les champs qui rendent la ligne unique

Le ci-dessous trouvera

tous les utilisateurs qui effectuent plus d'un paiement par jour avec le même numéro de compte

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

Mise à jour Si vous ne souhaitez inclure que ceux qui ont un ZIP distinct, vous pouvez d'abord obtenir un ensemble distinct, puis effectuer votre HAVING / GROUP BY

 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
Conrad Frix
la source
1
Remarquez que dans ses résultats 2a un compte de 4- Vous voudrez supprimer le Account_noregroupement, je pense.
JNK
Non attendez, je pense que l'original avait raison "tous les utilisateurs qui ont plus d'un paiement par jour avec le même numéro de compte."
Conrad Frix
il dit cela mais ses résultats montrent le contraire. Peut-être avoir les deux versions avec une note.
JNK
Merci pour vos réponses. Je pense que cela devrait le faire. Si je voulais maintenant ajouter un autre filtre qui vérifie si le code postal de facturation (même tableau, colonne différente) est différent pour la même date, comment modifierais-je cette requête?
Benjamin Muschko
Je ne peux pas résoudre l'exemple de sortie. Si nous supprimons le compte, nous obtiendrons trois lignes. Si nous supprimons la date et le compte, nous obtiendrons deux lignes 1,3 et 2,4. Je vais donc aller de l'avant et faire confiance aux mots sur la sortie
Conrad Frix
43

Essayez cette requête:

SELECT column_name
  FROM table_name
 GROUP BY column_name
HAVING COUNT(column_name) = 1;
utilisateur4019456
la source
4
soignée, mais cela ne répond pas à la question
Lambart
4

Je ne recommanderais pas le HAVINGmot - clé pour les débutants, c'est essentiellement à des fins d'héritage .

Je ne sais pas quelle est la clé de ce tableau (est-il entièrement normalisé , je me le demande?), Par conséquent j'ai du mal à suivre votre cahier des charges:

Je voudrais trouver tous les enregistrements pour tous les utilisateurs qui ont plus d'un paiement par jour avec le même numéro de compte ... De plus, il devrait y avoir un filtre qui ne compte que les enregistrements dont le code postal est différent.

J'ai donc pris une interprétation littérale.

Ce qui suit est plus détaillé mais pourrait être plus facile à comprendre et donc à maintenir (j'ai utilisé un CTE pour la table PAYMENT_TALLIESmais cela pourrait être un 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
              );
un jour quand
la source
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;
iryndin
la source