SQL-Abfrage zum Suchen von Datensätzen mit count> 1


176

Ich habe eine Tabelle mit dem Namen PAYMENT. In dieser Tabelle habe ich eine Benutzer-ID, eine Kontonummer, eine Postleitzahl und ein Datum. Ich möchte alle Datensätze für alle Benutzer finden, die mehr als eine Zahlung pro Tag mit derselben Kontonummer haben.

UPDATE: Zusätzlich sollte es einen Filter geben, der nur die Datensätze zählt, deren Postleitzahl unterschiedlich ist.

So sieht die Tabelle aus:

| user_id | account_no | zip | Datum |
| 1 | 123 | 55555 | 12-DEC-09 |
| 1 | 123 | 66666 | 12-DEC-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 |

Das Ergebnis sollte ungefähr so ​​aussehen:

| user_id | count |
| 1 | 2 |

Wie würden Sie dies in einer SQL-Abfrage ausdrücken? Ich dachte, ich würde mich selbst anschließen, aber aus irgendeinem Grund ist meine Zählung falsch.

Antworten:


344

Verwenden Sie die HAVING- Klausel und GROUP By für die Felder, die die Zeile eindeutig machen

Das Folgende wird finden

Alle Benutzer, die mehr als eine Zahlung pro Tag mit derselben Kontonummer haben

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

Update Wenn Sie nur diejenigen einschließen möchten, die eine bestimmte Postleitzahl haben, können Sie zuerst einen bestimmten Satz abrufen und dann HAVING / GROUP BY ausführen

 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
Beachten Sie in seinen Ergebnissen 2eine Anzahl von 4- Sie werden die Account_noGruppierung verwerfen wollen, denke ich.
JNK

Nein, ich denke, das Original war richtig. "Alle Benutzer, die mehr als eine Zahlung pro Tag mit derselben Kontonummer haben."
Conrad Frix

es sagt das, aber seine Ergebnisse zeigen etwas anderes. Vielleicht haben beide Versionen mit einem Hinweis.
JNK

Vielen Dank für Ihre Antworten. Ich denke das sollte es tun. Wenn ich jetzt einen weiteren Filter hinzufügen möchte, der prüft, ob die Postleitzahl der Abrechnung (dieselbe Tabelle, andere Spalte) für dasselbe Datum unterschiedlich ist, wie würde ich diese Abfrage ändern?
Benjamin Muschko

Ich kann die Beispielausgabe nicht auflösen. Wenn wir das Konto löschen, erhalten wir drei Zeilen. Wenn wir sowohl Datum als auch Konto löschen, erhalten wir zwei Zeilen 1,3 und 2,4. Also werde ich weitermachen und den Worten über die Ausgabe vertrauen
Conrad Frix

43

Versuchen Sie diese Abfrage:

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

4
ordentlich, aber das beantwortet die Frage nicht
Lambart

4

Ich würde das HAVINGSchlüsselwort nicht für Neulinge empfehlen , es ist im Wesentlichen für Legacy-Zwecke .

Ich bin mir nicht sicher, was der Schlüssel für diese Tabelle ist (ist sie vollständig normalisiert , frage ich mich?), Daher fällt es mir schwer, Ihrer Spezifikation zu folgen:

Ich möchte alle Datensätze für alle Benutzer finden, die mehr als eine Zahlung pro Tag mit derselben Kontonummer haben ... Außerdem sollte es einen Filter geben, der nur die Datensätze zählt, deren Postleitzahl unterschiedlich ist.

Also habe ich eine wörtliche Interpretation genommen.

Das Folgende ist ausführlicher, könnte aber leichter zu verstehen und daher zu pflegen sein (ich habe einen CTE für die Tabelle verwendet, PAYMENT_TALLIESaber es könnte ein sein 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;
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.