sql >> データベース >  >> RDS >> PostgreSQL

SQL:最も既知の値を持つ行を選択する方法は?

    痛いです。とても痛いです。

    この問題についての質問は明確ではありませんが、参照している「ユーザーID」はユーザー名であると想定しています。それが間違っている場合は、結果的に変更を加える必要があります。

    他の複雑なクエリと同様に、段階的に構築します。

    ステージ1:レコードごとにnull以外のフィールドはいくつありますか?

    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
    

    ステージ2:特定のユーザー名のフィールドの最大数はどれですか?

    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
    

    ステージ3:null以外のフィールドの最大数を持つ特定のユーザーの行を(すべて)選択します:

    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;
    

    これで、(たとえば)3つのフィールドすべてが入力された複数の行がある場合、それらのすべての行が返されます。ただし、これらの行から選択するための基準は指定していません。

    ここでの基本的な手法は、変更された要件に適合させることができます。重要なのは、サブクエリを作成してテストすることです。

    このSQLはどれもDBMSの近くにはありません。バグがある可能性があります。

    使用しているDBMSを指定していません。ただし、Oracleは、列エイリアスのASに問題はありませんが、テーブルエイリアスに使用されるAS表記を好まないようです。他のDBMSを使用している場合は、その小さな偏心について心配する必要はありません。



    1. SQL_CALC_FOUND_ROWS / FOUND_ROWS()はPHPでは機能しません

    2. SQLでのピボット演算子の理解

    3. Explainに基づくMySQLの最適化

    4. 注意:phpでの配列から文字列への変換