Как обеспечить случайный выбор строк из каждой из разных стран/городов в PostgreSQL?

#sql #postgresql #postgis

Вопрос:

Я работаю над PostgreSQL в dbeaver. В базе данных есть столбец addr:country и столбец addr:city . Данные содержат около 500 миллионов строк, поэтому мне нужно выполнить выборку ramdom для тестирования. Я намеревался случайным образом выбрать 1% данных. Однако сами данные могут быть сильно предвзятыми (поскольку есть большие страны и маленькие страны, поэтому для больших стран больше строк, а для небольших стран меньше), и я думаю о том, как провести справедливую выборку. Поэтому я хочу случайным образом выбрать одну или две строки из каждого города в каждой стране.

Сценарий, который я использую, изменен на основе чужого запроса, и мой сценарий:

 SELECT osm_id, way, tags, way_centroid, way_area, calc_way_area, area_diff, area_prct_diff, calc_perimeter, calc_count_vertices, building, "building:part", "type", amenity, landuse, tourism, office, leisure, man_made, "addr:flat", "addr:housename", "addr:housenumber", "addr:interpolation", "addr:street", "addr:city", "addr:postcode", "addr:country", length, width, height, osm_uid, osm_user, osm_version
    ROW_NUMBER() OVER ( PARTITION BY "addr:country", "addr:city" ) AS "cell_rn",
    COUNT(*)
    OVER ( PARTITION BY "addr:country", "addr:city") AS "cell_cnt"
FROM osm_qa.buildings
WHERE "addr:city" IS NOT NULL
AND "addr:country" IS NOT NULL
 

Он возвращает сообщение об ошибке: SQL Error [42601]: ERROR: syntax error at or near "(" Position: 1683 .

Я очень новичок в SQL, поэтому, вероятно, в сценарии много ошибок. Есть ли какой-либо способ принудительного случайного выбора одной/двух строк из каждой addr:city в каждой addr:country ?

Комментарии:

1. Вы упускаете , момент после osm_version

Ответ №1:

вы можете использовать оконную функцию dense_rank() для случайного пронумерования записей в разделе:

 with base_data as 
(
SELECT osm_id, way, tags, way_centroid, way_area, calc_way_area, area_diff, area_prct_diff, calc_perimeter, calc_count_vertices, building, "building:part", "type", amenity, landuse, tourism, office, leisure, man_made, "addr:flat", "addr:housename", "addr:housenumber", "addr:interpolation", "addr:street", "addr:city", "addr:postcode", "addr:country", length, width, height, osm_uid, osm_user, osm_version,
    ROW_NUMBER() OVER ( PARTITION BY "addr:country", "addr:city" ) AS "cell_rn",
    COUNT(*) OVER ( PARTITION BY "addr:country", "addr:city") AS "cell_cnt",
    dense_rank() over (partition by "addr:country", "addr:city" order by random()) as ranking,
FROM osm_qa.buildings
WHERE "addr:city" IS NOT NULL
AND "addr:country" IS NOT null
)
select 
*
from base_data
where ranking between 1 and 2