我有两张桌子:
我正在尝试创建一个按user_id密度对城市进行排名的表格。
因此,首先,我希望在“人员”表中获得一个表格,其中显示user_id以及每个user_id与之关联的城市。 user_id可以与多个城市相关联。
然后,我计划只计算每个城市的唯一user_ids,并根据user_id对城市进行从最密集到最不密集的排名。
答案 0 :(得分:1)
将逗号分隔的列转换为单独的行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
将有关城市的信息与关联的zipcodes的提取信息与用户相结合。 COUNT()
您的用户并使用窗口函数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
考虑一下你是否真的需要计算不同用户的zipcodes。用户是否可能多次使用相同的邮政编码?
如果是这种情况,您可以在第一个查询中使用DISTINCT
,这样您就不需要在排名查询中执行此操作:
select distinct
user_id,
unnest(string_to_array(zipcodes, ',')) AS zipcode
from people;
删除排名查询中的不同部分,您就可以了。