PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

SQL:Wie wähle ich die Zeile mit den meisten bekannten Werten aus?

Es wird schmerzhaft sein; sehr schmerzhaft.

Ihre Frage ist zu diesem Problem nicht klar, aber ich gehe davon aus, dass die "Benutzer-ID", auf die Sie sich beziehen, der Benutzername ist. Wenn das nicht stimmt, müssen entsprechende Änderungen vorgenommen werden.

Wie bei jeder komplexen Abfrage bauen Sie sie schrittweise auf.

Phase 1:Wie viele Nicht-Null-Felder gibt es pro Datensatz?

SELECT username, sex, date_of_birth, zip,
       CASE WHEN sex           IS NULL THEN 0 ELSE 1 END +
       CASE WHEN date_of_birth IS NULL THEN 0 ELSE 1 END +
       CASE WHEN zip           IS NULL THEN 0 ELSE 1 END AS num_non_null_fields
  FROM users_log

Phase 2:Wie viele Felder darf ein bestimmter Benutzername maximal haben?

SELECT username, MAX(num_non_null_fields) AS num_non_null_fields
  FROM (SELECT username, sex, date_of_birth, zip,
               CASE WHEN sex           IS NULL THEN 0 ELSE 1 END +
               CASE WHEN date_of_birth IS NULL THEN 0 ELSE 1 END +
               CASE WHEN zip           IS NULL THEN 0 ELSE 1 END AS num_non_null_fields
          FROM users_log
       ) AS u
 GROUP BY username

Stufe 3:Wählen Sie (alle) Zeilen für einen bestimmten Benutzer mit dieser maximalen Anzahl von Nicht-Null-Feldern aus:

SELECT u.username, u.sex, u.date_of_birth, u.zip
  FROM (SELECT username, MAX(num_non_null_fields) AS num_non_null_fields
          FROM (SELECT username, sex, date_of_birth, zip,
                       CASE WHEN sex           IS NULL THEN 0 ELSE 1 END +
                       CASE WHEN date_of_birth IS NULL THEN 0 ELSE 1 END +
                       CASE WHEN zip           IS NULL THEN 0 ELSE 1 END AS num_non_null_fields
                  FROM users_log
               ) AS u
         GROUP BY username
       ) AS v
  JOIN (SELECT username, sex, date_of_birth, zip,
               CASE WHEN sex           IS NULL THEN 0 ELSE 1 END +
               CASE WHEN date_of_birth IS NULL THEN 0 ELSE 1 END +
               CASE WHEN zip           IS NULL THEN 0 ELSE 1 END AS num_non_null_fields
          FROM users_log
       ) AS u
    ON u.username = v.username AND u.num_non_null_fields = v.num_non_null_fields;

Wenn nun jemand mehrere Zeilen hat, in denen (sagen wir) alle drei Felder ausgefüllt sind, werden alle diese Zeilen zurückgegeben. Sie haben jedoch keine Kriterien angegeben, nach denen zwischen diesen Zeilen ausgewählt werden soll.

Die Grundtechniken können dabei an geänderte Anforderungen angepasst werden. Der Schlüssel liegt darin, die Unterabfragen zu erstellen und zu testen, während Sie fortfahren.

Nichts von diesem SQL war in der Nähe eines DBMS; es könnten Fehler darin sein.

Sie haben nicht angegeben, welches DBMS Sie verwenden. Es scheint jedoch, dass Oracle die für Tabellenaliase verwendete AS-Notation nicht mögen wird, obwohl es kein Problem mit AS bei Spaltenaliasen hat. Wenn Sie ein anderes DBMS verwenden, sollten Sie sich über diese geringfügige Exzentrizität keine Sorgen machen müssen.