sql >> Base de Datos >  >> RDS >> PostgreSQL

SQL:¿cómo seleccionar la fila con la mayoría de los valores conocidos?

Va a ser doloroso; muy doloroso.

Su pregunta no es clara sobre este problema, pero supongo que la 'identificación de usuario' a la que se refiere es el nombre de usuario. Hay modificaciones consecuentes para hacer si eso está mal.

Al igual que con cualquier consulta compleja, constrúyala en etapas.

Etapa 1:¿Cuántos campos no nulos hay por registro?

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

Etapa 2:¿Cuál es el número máximo de campos para un nombre de usuario dado?

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

Etapa 3:Seleccione (todas) las filas para un usuario dado con ese número máximo de campos no nulos:

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;

Ahora, si alguien tiene varias filas con (digamos) los tres campos completos, se devolverán todas esas filas. Sin embargo, no ha especificado ningún criterio para elegir entre esas filas.

Las técnicas básicas aquí se pueden adaptar a cualquier cambio en los requisitos. La clave es crear y probar las subconsultas sobre la marcha.

Nada de este SQL ha estado cerca de un DBMS; podría haber errores en él.

No ha especificado qué DBMS está utilizando. Sin embargo, parece que a Oracle no le gustará la notación AS utilizada para los alias de tablas, aunque no tiene ningún problema con los alias de AS en columnas. Si está utilizando cualquier otro DBMS, no debería preocuparse por esa pequeña excentricidad.