将逗号分隔的邮政编码字段转换为城市列表

Turn a field of comma-separated zip codes into a list of cities

我有两个 table:

  1. 人,包含 user_id 列(唯一)和邮政编码(逗号分隔值;单个值中可能有多个邮政编码);
  2. 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;

删除排名查询中的不同部分,您就可以开始了。