Pregunta

Fondo

Más de 5300 filas duplicadas:

"id","latitude","longitude","country","region","city"
"2143220","41.3513889","68.9444444","KZ","10","Abay"
"2143218","40.8991667","68.5433333","KZ","10","Abay"
"1919381","33.8166667","49.6333333","IR","34","Ab Barik"
"1919377","35.6833333","50.1833333","IR","19","Ab Barik"
"1919432","29.55","55.5122222","IR","29","`Abbasabad"
"1919430","27.4263889","57.5725","IR","29","`Abbasabad"
"1919413","28.0011111","58.9005556","IR","12","`Abbasabad"
"1919435","36.5641667","61.14","IR","30","`Abbasabad"
"1919433","31.8988889","58.9211111","IR","30","`Abbasabad"
"1919422","33.8666667","48.3","IR","23","`Abbasabad"
"1919420","33.4658333","49.6219444","IR","23","`Abbasabad"
"1919438","33.5333333","49.9833333","IR","34","`Abbasabad"
"1919423","33.7619444","49.0747222","IR","24","`Abbasabad"
"1919419","34.2833333","49.2333333","IR","19","`Abbasabad"
"1919439","35.8833333","52.15","IR","35","`Abbasabad"
"1919417","35.9333333","52.95","IR","17","`Abbasabad"
"1919427","35.7341667","51.4377778","IR","26","`Abbasabad"
"1919425","35.1386111","51.6283333","IR","26","`Abbasabad"
"1919713","30.3705556","56.07","IR","29","`Abdolabad"
"1919711","27.9833333","57.7244444","IR","29","`Abdolabad"
"1919716","35.6025","59.2322222","IR","30","`Abdolabad"
"1919714","34.2197222","56.5447222","IR","30","`Abdolabad"

Detalles adicionales:

  • Base de datos PostgreSQL 8.4
  • Linux

Problema

Algunos valores son duplicados obvios ("abay" porque las regiones coinciden y "ab barik" porque las dos ubicaciones están muy cerca), otras no son tan obvias (y pueden ni siquiera ser duplicados reales):

"1919430","27.4263889","57.5725","IR","29","`Abbasabad"
"1919435","36.5641667","61.14","IR","30","`Abbasabad"

El objetivo es eliminar todos los duplicados.

Preguntas

Dada una tabla de valores como los datos de CSV anteriores:

  • ¿Cómo eliminarías los duplicados?
  • ¿Qué funciones PostgreSQL centradas en GEO utilizarías?
  • ¿Qué otros criterios usarías para reducir los duplicados?

Actualizar

Código de ejemplo semi-trabajo para seleccionar nombres de ciudad duplicados dentro del mismo país que están muy cerca (dentro de 10 km):

select
  c1.country, c1.name, c1.region_id, c2.region_id, c1.latitude_decimal, c1.longitude_decimal, c2.latitude_decimal, c2.longitude_decimal
from
  climate.maxmind_city c1,
  climate.maxmind_city c2
where
  c1.country = 'BE' and
  c1.id <> c2.id and
  c1.country = c2.country and
  c1.name = c2.name and
  (c1.latitude_decimal <> c2.latitude_decimal or c1.longitude_decimal <> c2.longitude_decimal) and
  earth_distance(
    ll_to_earth( c1.latitude_decimal, c1.longitude_decimal ),
    ll_to_earth( c2.latitude_decimal, c2.longitude_decimal ) ) <= 10
order by
  country, name

Ideas

Enfoque de dos fases:

  1. Elimine los duplicados obvios (mismo país, región y nombre de la ciudad) eliminando el min (ID).
  2. Elimine aquellos que están muy cerca el uno del otro, teniendo el mismo nombre y país. Esto podría eliminar algunas ciudades legítimas, pero casi ninguna consecuencia.

¡Gracias!

¿Fue útil?

Solución 2

Esto elimina la segunda ciudad muy cerca de una ciudad del mismo nombre en el mismo país:

delete from climate.maxmind_city mc where id in (
select
  max(c1.id)
from
  climate.maxmind_city c1,
  climate.maxmind_city c2
where
  c1.id <> c2.id and
  c1.country = c2.country and
  c1.name = c2.name and
  earth_distance(
    ll_to_earth( c1.latitude_decimal, c1.longitude_decimal ),
    ll_to_earth( c2.latitude_decimal, c2.longitude_decimal ) ) <= 35
group by
  c1.country, c1.name
order by
  c1.country, c1.name
)

Otros consejos

Encontrar duplicados es simple:

select
  max(id) as this_should_stay,
  latitude,
  longitude,
  country,
  region,
  city
FROM
  your_table
group by
  latitude,
  longitude,
  country,
  region,
  city
having count(*) > 1;

Agregar código para eliminar duplicados según esto es simple:

delete from your_table where id not in (
    select
      max(id) as this_should_stay
    FROM
      your_table
    group by
      latitude,
      longitude,
      country,
      region,
      city
)

Nota falta de tener en la consulta de eliminación.

Si sus datos se han importado a través de archivos CSV y con el código (PHP), puede evitar la entrada de duplicados con la condición de colocación en el código PHP. Si la ciudad que insertó ya existe, haga que el bucle continúe con el siguiente registro y omita el registro actual.

Pruebe esto si sigue de esta manera para importar datos en la base de datos.

Gracias.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top