POSTGRES- 我想在Employees表中更新Employees.zipcode_mod列中的'invalid zipcodes'(Employees.zipcode),如果它们在Ref_Zips.zip5中不存在则无效
更新规则是查找3个字符或长的所有无效zipcode,并在Tmp_Agg_Zips.zip列的前三位数字上匹配它们,并使用Tmp_Agg_Zips.emp_cnt最高的Tmp_Agg_Zips.zip更新Employees.zipcode_mod。如果多个Tmp_Agg_Zips.zip值之间存在平局,则获取“最高”的zip值。
如果无效zipcode
超过3个字符,但其前三个数字与Tmp_Agg_Zips.zip
的前三个数字中的任何一个都不匹配,或者无效zipcode
小于3个字符或无效,然后只需使用Employees.zipcode_mod
更新Tmp_Agg_Zips.zip
,其最大值为Tmp_Agg_Zips.emp_cnt
,无论前三位数如何。在下面的示例中,Ex-88888和null更新为10012。
这适用于 Postgres 8.4 。
Gender | zipcode | zipcode_mod
M | 99574 |
F | 99574 |
F | 10012 |
F | 10012 |
F | 10012 |
F | 19001 |
M | 100 | 10012
M | 190 | 19001
M | 19 | 10012
F | null | 10012
F | 88888 | 10012
F | 8888 | 10012
zip | emp_cnt
99574 | 2
10012 | 3
19001 | 1
zip5
99574
10012
19001
答案 0 :(得分:1)
我添加了一个COALESCE()
子句来捕获没有找到匹配替代的情况。并将默认值的计算放入子查询中以供多次使用。
UPDATE employees e
SET zipcode_mod =
CASE WHEN length(e.zipcode) > 2 THEN
COALESCE((
SELECT t.zip
FROM tmp_agg_zips t
WHERE substr(t.zipcode, 1, 3) = substr(e.zipcode, 1, 3)
ORDER BY t.emp_cnt DESC, t.zip -- lowest zip for mult. emp_cnt
LIMIT 1
), t0.zip)
ELSE
t0.zip
END
FROM (
SELECT zip
FROM tmp_agg_zips
ORDER BY emp_cnt DESC, t.zip
LIMIT 1
) t0
WHERE NOT EXISTS (
SELECT *
FROM ref_zips r
WHERE r.zip5 = e.zipcode
)
此查询适用于PostgreSQL的旧版本:
UPDATE employees e
SET zipcode_mod =
CASE WHEN length(e.zipcode) > 2 THEN (
SELECT t.zip
FROM tmp_agg_zips t
WHERE substr(t.zipcode, 1, 3) = substr(e.zipcode, 1, 3)
ORDER BY t.emp_cnt DESC, t.zip -- lowest zip for mult. emp_cnt
LIMIT 1
)
ELSE (
SELECT zip
FROM tmp_agg_zips
ORDER BY emp_cnt DESC, t.zip
LIMIT 1
)
END
WHERE NOT EXISTS (
SELECT *
FROM ref_zips r
WHERE r.zip5 = e.zipcode
)
在 PostgreSQL 9.1 中,CTE应该效果更佳:
WITH x AS (
SELECT zip
FROM tmp_agg_zips
ORDER BY emp_cnt DESC, t.zip
LIMIT 1
)
UPDATE employees e
SET zipcode_mod =
CASE WHEN length(e.zipcode) > 2 THEN (
SELECT t.zip
FROM tmp_agg_zips t
WHERE left(t.zipcode, 3) = left(e.zipcode, 3)
ORDER BY t.emp_cnt DESC, t.zip -- pick lowest zip
LIMIT 1
)
ELSE
x.zip
END
FROM x
WHERE NOT EXISTS (
SELECT *
FROM ref_zips r
WHERE r.zip5 = e.zipcode
)
如果tmp_agg_zips
中有多个行具有相同(最高)emp_cnt
,我选择“最低”zip
。你没有具体说明如何打破这些联系。
BTW,邮政编码的不同列名对我没有帮助。表格限定列名称可以做得更好。