Nik*_*lin 1 sql postgresql deduplication
我有用户表(用户名,性别,date_of_birth,zip),其中用户的id是永久性的,但用户可能在过去多次注册,有时他填写所有数据,有时不填写.除此之外,他可以改变居住地(在这种情况下,zip可以改变).
所以查询
SELECT username, sex, date_birth, zip FROM users_log WHERE username IN('user1', 'user2', 'user3')
Run Code Online (Sandbox Code Playgroud)
返回以下结果:
"user1";"M";"1982-10-04 00:00:00";"6320"
"user2";"";"";"1537"
"user3";"";"";"1537"
"user3";"";"";"1000"
"user3";"";"";"1000"
"user3";"";"1979-05-29 00:00:00";"1000"
"user3";"";"";"1537"
"user3";"";"1979-05-29 00:00:00";"1000"
"user1";"";"";"1000"
"user3";"";"";"1537"
Run Code Online (Sandbox Code Playgroud)
在这种情况下,用户1改变了住所; 邮政编码改变了; 并且"属于"他的第二行不包含人口统计数据.User3还有多条记录,只有两条记录包含人口统计数据.
我想要做的是绑定用户包含关于他的最多数据的行,并考虑包含在具有最知名值的行中的zip.有谁知道如何编写适当的查询?
谢谢!
这会很痛苦; 很痛苦.
你的问题不清楚这个问题,但我假设你所指的'用户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
Run Code Online (Sandbox Code Playgroud)
第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
Run Code Online (Sandbox Code Playgroud)
第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;
Run Code Online (Sandbox Code Playgroud)
现在,如果某人有多行(例如)填写了所有三个字段,那么将返回所有这些行.但是,您没有指定在这些行之间进行选择的任何标准.
这里的基本技术可以适应任何变化的要求.关键是在你去的时候构建和测试子查询.
这个SQL都不在DBMS附近; 它可能存在缺陷.
您尚未指定要使用的DBMS.但是,似乎Oracle不会喜欢用于表别名的AS表示法,尽管它对列别名的AS没有问题.如果您正在使用任何其他DBMS,您不必担心这种轻微的怪癖.
幸运的是你正在使用PostgreSQL.通过将boolean转换为整数来计算填充的字段更容易:
SELECT username,
(
(sex is not null)::int
+ (date_birth_birth is not null)::int
+ (zip is not null)::int
) / 3.0 as percent_complete
FROM users_log
Run Code Online (Sandbox Code Playgroud)
您的代码目标与此问题具有相似性:
Postgresql:按真OR子句的数量计算排名
| 归档时间: |
|
| 查看次数: |
189 次 |
| 最近记录: |