将逗号分隔的邮政编码字段转换为城市列表
Turn a field of comma-separated zip codes into a list of cities
我有两个 table:
- 人,包含 user_id 列(唯一)和邮政编码(逗号分隔值;单个值中可能有多个邮政编码);
- location,包含邮政编码、城市和州列(每个邮政编码都与一个城市和州相关联,table 包括整个美国)。
我正在尝试创建一个按 user_id 密度对城市进行排名的 table。
所以,首先,我想要一个 table 显示 user_id 以及每个 user_id 在 "people" table 中关联的城市.一个 user_id 可以关联多个城市。
然后,我计划只计算每个城市的独特 user_id 并根据 user_id 对城市从最密集到最不密集的城市进行排名。
将逗号分隔的列值转换为单独的行
使用 unnest()
将逗号分隔的列变成单独的行,首先使用 string_to_array()
:
从字符串构建数组
select
user_id,
unnest(string_to_array(zipcodes, ',')) AS zipcode
from people
正在生成测试数据:
create table people(user_id int, zipcodes text);
insert into people values (1, '22333,12354,45398,12398');
into people values (2, '54389,45398,12398');
insert into people values (3, '34534,12398,94385');
结果:
user_id | zipcode
---------+---------
1 | 22333
1 | 12354
1 | 45398
1 | 12398
2 | 54389
2 | 45398
2 | 12398
3 | 34534
3 | 12398
3 | 94385
按用户密度对城市进行排名
使用 LEFT JOIN
将有关城市的信息与有关相关邮政编码的提取信息与用户相结合。 COUNT()
您的用户并使用 window 函数 DENSE_RANK()
分配排名位置。在这种情况下,领带的位置相同。
查询:
SELECT
l.city
, COUNT(DISTINCT p.user_id) AS distinct_users -- is distinct really needed?
, DENSE_RANK() OVER (ORDER BY COUNT(DISTINCT p.user_id) DESC) AS city_ranking
FROM location l
LEFT JOIN (
select
user_id,
unnest(string_to_array(zipcodes, ',')) AS zipcode
from people
) p USING ( zipcode )
GROUP BY l.city
ORDER BY city_ranking
正在生成测试数据:
create table location(zipcode text, city text);
insert into location values
('22333', 'City1'),
('12354', 'City2'),
('45398', 'City3'),
('12398', 'City4'),
('54389', 'City5'),
('34534', 'City6'),
('94385', 'City7');
结果:
city | distinct_users | city_ranking
-------+----------------+--------------
City4 | 3 | 1
City3 | 2 | 2
City2 | 1 | 3
City1 | 1 | 3
City5 | 1 | 3
City6 | 1 | 3
City7 | 1 | 3
补充说明
考虑一下您是否真的需要计算不同用户的邮政编码。用户是否可能多次使用相同的邮政编码?
如果是这样,您可以在第一个查询中使用 DISTINCT
,这样您就不需要在排名查询中这样做:
select distinct
user_id,
unnest(string_to_array(zipcodes, ',')) AS zipcode
from people;
删除排名查询中的不同部分,您就可以开始了。
我有两个 table:
- 人,包含 user_id 列(唯一)和邮政编码(逗号分隔值;单个值中可能有多个邮政编码);
- location,包含邮政编码、城市和州列(每个邮政编码都与一个城市和州相关联,table 包括整个美国)。
我正在尝试创建一个按 user_id 密度对城市进行排名的 table。
所以,首先,我想要一个 table 显示 user_id 以及每个 user_id 在 "people" table 中关联的城市.一个 user_id 可以关联多个城市。
然后,我计划只计算每个城市的独特 user_id 并根据 user_id 对城市从最密集到最不密集的城市进行排名。
将逗号分隔的列值转换为单独的行
使用 unnest()
将逗号分隔的列变成单独的行,首先使用 string_to_array()
:
select
user_id,
unnest(string_to_array(zipcodes, ',')) AS zipcode
from people
正在生成测试数据:
create table people(user_id int, zipcodes text);
insert into people values (1, '22333,12354,45398,12398');
into people values (2, '54389,45398,12398');
insert into people values (3, '34534,12398,94385');
结果:
user_id | zipcode
---------+---------
1 | 22333
1 | 12354
1 | 45398
1 | 12398
2 | 54389
2 | 45398
2 | 12398
3 | 34534
3 | 12398
3 | 94385
按用户密度对城市进行排名
使用 LEFT JOIN
将有关城市的信息与有关相关邮政编码的提取信息与用户相结合。 COUNT()
您的用户并使用 window 函数 DENSE_RANK()
分配排名位置。在这种情况下,领带的位置相同。
查询:
SELECT
l.city
, COUNT(DISTINCT p.user_id) AS distinct_users -- is distinct really needed?
, DENSE_RANK() OVER (ORDER BY COUNT(DISTINCT p.user_id) DESC) AS city_ranking
FROM location l
LEFT JOIN (
select
user_id,
unnest(string_to_array(zipcodes, ',')) AS zipcode
from people
) p USING ( zipcode )
GROUP BY l.city
ORDER BY city_ranking
正在生成测试数据:
create table location(zipcode text, city text);
insert into location values
('22333', 'City1'),
('12354', 'City2'),
('45398', 'City3'),
('12398', 'City4'),
('54389', 'City5'),
('34534', 'City6'),
('94385', 'City7');
结果:
city | distinct_users | city_ranking
-------+----------------+--------------
City4 | 3 | 1
City3 | 2 | 2
City2 | 1 | 3
City1 | 1 | 3
City5 | 1 | 3
City6 | 1 | 3
City7 | 1 | 3
补充说明
考虑一下您是否真的需要计算不同用户的邮政编码。用户是否可能多次使用相同的邮政编码?
如果是这样,您可以在第一个查询中使用 DISTINCT
,这样您就不需要在排名查询中这样做:
select distinct
user_id,
unnest(string_to_array(zipcodes, ',')) AS zipcode
from people;
删除排名查询中的不同部分,您就可以开始了。