这会很痛苦;非常痛苦。
您的问题不清楚这个问题,但我假设您所指的“用户 ID”是用户名。如果这是错误的,则需要进行相应的修改。
与任何复杂的查询一样,分阶段构建它。
第 1 阶段:每条记录有多少个非空字段?
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 阶段:为具有最大数量的非空字段的给定用户选择(全部)行:
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;
现在,如果某人有多行(比如说)填写了所有三个字段,那么所有这些行都将被返回。但是,您没有指定在这些行之间进行选择的任何标准。
这里的基本技术可以适应任何变化的需求。关键是随时构建和测试子查询。
这些 SQL 都没有靠近 DBMS。它可能有错误。
您尚未指定您使用的 DBMS。然而,Oracle 似乎不喜欢用于表别名的 AS 表示法,尽管它在列别名上使用 AS 没有问题。如果您使用任何其他 DBMS,则不必担心这种小怪癖。