PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

SQL :comment sélectionner la ligne avec les valeurs les plus connues ?

Ça va être douloureux; très douloureux.

Votre question n'est pas claire à propos de ce problème, mais je suppose que "l'identifiant d'utilisateur" auquel vous faites référence est le nom d'utilisateur. Il y a des modifications consécutives à faire si c'est faux.

Comme pour toute requête complexe, construisez-la par étapes.

Étape 1 :Combien de champs non nuls y a-t-il par enregistrement ?

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

Etape 2 :Quel est le nombre maximum de champs pour un nom d'utilisateur donné ?

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

Étape 3 :Sélectionnez (toutes) les lignes pour un utilisateur donné avec ce nombre maximal de champs non nuls :

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;

Maintenant, si quelqu'un a plusieurs lignes avec (disons) les trois champs remplis, alors toutes ces lignes seront renvoyées. Cependant, vous n'avez spécifié aucun critère permettant de choisir entre ces lignes.

Les techniques de base ici peuvent être adaptées à toute modification des exigences. La clé est de créer et de tester les sous-requêtes au fur et à mesure.

Aucun de ces SQL n'a été proche d'un SGBD ; il pourrait y avoir des bugs.

Vous n'avez pas spécifié le SGBD que vous utilisez. Cependant, il semble qu'Oracle n'aime pas la notation AS utilisée pour les alias de table, bien qu'il n'ait aucun problème avec AS sur les alias de colonne. Si vous utilisez un autre SGBD, vous ne devriez pas avoir à vous soucier de cette excentricité mineure.