¿Cómo deberían almacenarse las direcciones geográficas internacionales en una base de datos relacional?

Dada la tarea de almacenar direcciones geográficas internacionales en una tabla relacional, ¿cuál es el esquema más flexible? ¿Debería dividirse cada parte de la dirección en sus propios campos, o debería ser más como texto libre?

¿Tiene algún sentido separar la dirección con diferentes formatos en diferentes tablas? Por ejemplo, ¿tiene una tabla para USAAddress, CanadianAddress, UKAddress …?

Resumiré mis pensamientos de mi entrada en el blog: una lección sobre el almacenamiento de direcciones .

En mi proyecto actual [Trabajo para una empresa de logística] almacenamos direcciones internacionales. He hecho investigaciones sobre direcciones en todo el mundo en el diseño de esta parte de la base de datos. Hay muchos formatos diferentes. En el mundo occidental, tendemos a usar un formato bastante uniforme: algunas diferencias, pero en su mayoría son:

  • Número de calle – Numérico
  • Nombre de casa o edificio – [VarChar – en el Reino Unido algunas casas / edificios se identifican por nombre, no por número]
  • Sufijo de número de calle [VarChar, aunque en la mayoría de los casos, Char (1) sería suficiente]
    • A, B, etc.
  • Nombre de la calle [VarChar]
  • Tipo de calle [VarChar o Int si tiene una tabla StreetTypes]
    • Hasta ahora, he encontrado 262 tipos únicos en el mundo de habla inglesa, es probable que haya más y no olvides otros idiomas, es decir, Strasse, Rue, etc.
  • Dirección de la calle [VarChar (2)]
    • N, E, S, W, NE, SE, NW, SW
  • Tipo de dirección [VarChar o Int si tiene una tabla AddressTypes]
    • Apartado postal
    • Apartamento
    • edificio
    • Piso
    • Oficina
    • Suite
    • etc …
  • Identificador de tipo de dirección [VarChar]
    • es decir, número de casilla, número de apartamento, número de piso: recuerde que los números de los departamentos y las oficinas a veces tienen información alfanumérica, como 1A
  • Municipio local [VarChar o Int si tiene una tabla de Municipios]
    • Por ejemplo, si su aldea / aldea aparece en la dirección antes de la ciudad.
  • Ciudad / Pueblo [VarChar o Int si tiene una tabla de Ciudades]
  • Distrito gobernante [VarChar o Int si tiene una tabla de Distritos]
    • Estado (EE. UU.)
    • Provincia (Canadá)
    • Distrito Federal (México)
    • Condado (Reino Unido)
    • etc …
  • Área postal [VarChar]
    • Zip (EE. UU.)
    • Código postal (Canadá, México)
    • Código postal (Reino Unido)
  • País [VarChar o Int si tiene una tabla Países]

Esto parece abarcar la mayoría de los países, pero el orden de los campos puede mostrarse de forma diferente. Puede encontrar una lista de formatos de visualización en http://www.bitboost.com/ref/international-address-formats.html#Formats

Por ejemplo, en muchos países, el código postal cae antes del nombre de la ciudad y el número de la calle cae después del nombre de la calle. En Canadá, EE. UU. Y el Reino Unido, el número de calle precede al nombre de la calle y el código postal (o ZIP) aparece después del nombre de la ciudad.

En respuesta a su pregunta sobre la separación de las direcciones en diferentes países, no lo sugeriría, sino que haría la vida más difícil en otras áreas, por ejemplo, informar. El formato que he proporcionado cubre todas las direcciones en nuestra base de datos de logística que cubre los Estados Unidos, Canadá, México y el Reino Unido sin ningún problema. También cubre todas nuestras direcciones europeas, chinas, japonesas y malasias. No puedo hablar en otros países pero aún no he tenido que almacenar una dirección de un país que estos campos no admitirán.

No sugiero ir con el formato Address1, Address2, Address3 sugerido por otros y visto en muchas bases de datos porque el análisis de la información de la dirección de una cadena alfanumérica no es tan simple como podría parecer, especialmente si los datos no se ingresan correctamente. debido a información errónea, errores tipográficos, errores ortográficos, etc. Si separa sus campos, puede usar algoritmos de distancia para verificar el significado probable, usar la probabilidad para verificar el nombre de la calle contra el código postal y el número de la calle o verificar provincia y ciudad contra el nombre de la calle, etc. haciendo algo de eso cuando tienes una cadena que denota tu dirección completa. No es un asunto trivial por ningún tramo de la imaginación.

QA en una base de datos de direcciones es un dolor de cabeza, punto. La forma más sencilla de simplificar su vida en esta área es asegurarse de que todos los campos contengan solo una información que pueda verificarse automáticamente como correcta en el momento de la entrada. Los algoritmos de probabilidad, distancia y expresiones regulares pueden verificar la validez de la entrada y proporcionar retroalimentación al usuario sobre cuál fue su error y sugerir las correcciones adecuadas.

Una advertencia que debe tener en cuenta son las carreteras con nombres que también son tipos de calles; si está cubriendo Canadá, debe tener en cuenta “Avenue Road” en Toronto, que le hará perder mucho si utiliza la dirección1, 2 , 3 formato. Es probable que esto también ocurra en otros lugares, aunque no estoy al tanto de ellos, ¡esta sola instancia fue suficiente para gritar WTF!

Tenga cuidado de no analizar en exceso los formatos de direcciones. Cuando lo haga, es muy probable que termine con una especificación que la mayoría de los usuarios tendrán que evitar , forzándolos a usar los campos incorrectos, o solo llenando los campos primarios e ignorando los campos adicionales.

Mantén las cosas simples.

Un tipo de calle como el mencionado por BenAlabaster causará problemas cuando empiece a trabajar con idiomas diferentes a los de aislamiento de idiomas como el inglés o el español.

Para mostrarte lo mal que pueden estar las cosas en la naturaleza: la “Henriette Roland Holststraat” en Amsterdam, construida a partir de “Henriette” + “Roland Holst” + “straat”, que puede abreviarse como “Roland Holststraat”, o ” Roland Holststr. “, O mal escrito como” HRHolststr. ” o “Henriette Roland-Holst straat”, dependiendo del clima. A menos que tenga un registro de calles actualizado para cada país en la tierra, no irá a ninguna parte.

Y, por último, tenga cuidado de que en algunos países multilingües, los nombres pueden ser diferentes de un idioma a otro. Por ejemplo, en Bruselas, donde muchas calles tienen nombres tanto en francés como en neerlandés: “Avenu du Port” y “Havenlaan”, según el idioma preferido del destinatario. (Google Maps muestra ambos nombres alternativamente, solo para estar seguros).

Puede tratar de idear todo tipo de trucos ingeniosos aquí, pero son los representantes de ventas. va a entender esto?

Eso depende de lo que quieras hacer con eso.

Siempre me resulta más fácil usar direcciones para otros fines (como la verificación de los datos de USPS o las tarifas de envío de UPS / FEDEX) si están separados.

Esto es lo que normalmente uso para las direcciones:

  • Dirección Línea 1
  • Dirección Línea 2
  • Dirección Línea 3
  • Ciudad
  • Región
  • Código postal
  • Condado
  • País

En respuesta a la edición: para la mayoría de las situaciones, no veo el uso. La tabla que enumeré arriba tiene suficientes campos (y es lo suficientemente genérica) para la mayoría de las direcciones de país.

Dirección

Como un aspecto opuesto a la excelente respuesta que brindó @BenAlabaster, simplemente podría tener:

address TEXT(300) postal_code VARCHAR(15) country_code VARCHAR(2) 

Los diseños de formularios del lado del cliente pueden ser tan complejos como lo considere adecuado (o utilizar una entrada de varias líneas donde el usuario puede escribir manualmente su dirección). A continuación, puede agregar los saltos de línea en la dirección donde sea necesario.

País

Su tabla de países se verá de la siguiente manera:

 country_code VARCHAR(2) country_name VARCHAR(255) 

Además, podría tener uno de los siguientes:

 postal_code_required TINYINT(1) postal_code_regex VARCHAR(255) NULL DEFAULT NULL 

Luego use las siguientes listas para diseñar su tabla de países:

  • Wikipedia: ISO 3166-1 alpha-2
  • GitHub: Países sin códigos postales
  • GitHub: lista de países de MySQL
  • Lista regex del código postal

Aquí hay una anécdota para cualquiera que tropieza con esta pregunta:

Hablo como una persona que ha vivido y trabajado en muchos continentes (Europa, Asia, América del Norte). Según mi experiencia, y la experiencia de las personas con las que trabajo, ha sido mucho más fácil para nosotros usar sistemas que hacen lo siguiente:

  1. Proporcione tres líneas en las que escribiré una dirección. Pase estas tres líneas a su servicio postal local mientras las escribo, textualmente. Permítanme usar cualquier conjunto de caracteres que quiera; usa UTF-8 o algo mejor.
  2. Si su sistema tiene requisitos comerciales que requieren que especifique información específica (como código postal, prefectura, estado, etc.), solicítelos por separado. Por requisitos comerciales, me refiero a cosas como el análisis; estos bits de información no deberían compartirse con su servicio postal local (a menos que también escribiera la misma información en una de las tres líneas del punto 1 anterior).
  3. Tenga un menú desplegable que me pida que especifique la ubicación categórica de la dirección que proporcioné en las líneas del Punto 1 anterior, tal vez el País.
  4. Si debe analizar la información que proporciono en las líneas del Punto 1, use mi respuesta al Punto 3 para seleccionar expresiones regulares. Ejecute esa expresión regular contra la información del punto 1 para analizarla. Intenta llenar los elementos de la interfaz de usuario del Punto 2 usando la salida de tu expresión regular. Si corrijo esa información autocompletada, use el hecho de que la cambié para mejorar su expresión regular. Del mismo modo, en la medida de lo posible, dame la oportunidad de revisar y corregir el resultado de tu expresión regular: nadie sabe mejor que yo lo que pretendo comunicar.

Creo que los sistemas construidos de esta forma me hacen la vida más fácil. Particularmente cuando estoy enviando correo a un sistema postal sobre el cual su firma prácticamente no tiene ningún conocimiento interno funcional.

Si su empresa tiene conocimiento interno sobre sistemas postales particulares, use mi selección en el Punto 3 para informar qué vista me muestra. Mucha gente sabe lo que el sistema postal de EE. UU. Espera en el empaquetado; si selecciono US en el Punto 3, siéntase libre de hacer que la vista parezca apropiada para una dirección de EE. UU. Si selecciono un país sobre el cual su empresa no sabe nada, visualice tres líneas genéricas y déjeme hacer el rest; no me obligue a usar ASCII.

Y seamos realistas aquí: construir una base de datos completa y enciclopédica de todos los sistemas postales mundiales (públicos y privados) es una tarea hercúlea en el mejor de los casos, sino imposible. Hay, por ejemplo, sistemas postales en los que solo el operador local de última milla realmente sabe dónde se encuentra una dirección. A veces es extremadamente útil poder pasar notas a ese operador en el paquete. Y mapear el conocimiento local de cada portador de portada en su base de datos es de hecho una tarea imposible.

Solo pregúntale a Gödel. (Y luego pregúntese si está tratando de usar un sistema axiomático para modelar un universo de discurso, dar o tomar algún tipo de aritmética como la teoría de conjuntos o el álgebra relacional).

Comentario de la respuesta de Ben Alabaster: para formatear las direcciones según el país, puede usar una tabla de formato que tenga el orden de las columnas para cada país como filas separadas.

  • AddressFormat (CountryCode, FieldName, FieldOrder)

El orden de campo se puede codificar para usar diseños de cuadrícula complejos también.

No tiene sentido separar las direcciones por país. Esto será caótico a medida que aumente el número de países y usted tendrá problemas si quiere encontrar todas las direcciones de, digamos, un cliente internacional. Tener un tipo de dirección sugerido por Ben también podría generar ambigüedades cuando tienes una dirección que tiene un número de edificio y un número de departamento. Podría estar en un complejo de apartamentos donde cada edificio tiene un nombre diferente. Esto es muy común en India.

La única forma es dividirlos en:

 Name varchar, Title varchar, StreetAddress varchar, StreetAddressLine2 varchar, zipCode varchar, City varchar, Province varchar, Country lookup 

ya que casi todos los países tienen su propio estándar para tener datos de direcciones, y cada país tiene un formato diferente de códigos postales.
Puede tener una pequeña muestra de problemas en mi publicación de una pregunta similar.

Esto no debería tener sentido para separar direcciones para cada país, ya que hay países donde tiene pocas convenciones de direcciones. Algunas convenciones populares incluyen no tener calles en pueblos pequeños, solo el nombre y el número del pueblo, mientras que las calles están en las direcciones de las ciudades más grandes. Me enteré de que en la capital de Hungría, Budapest, hay pocas calles con el mismo nombre (las diferencia por el número del distrito de la ciudad), mientras que otras ciudades no tienen esas direcciones (alguien de Hungría puede confirmar si esto es cierto). Entonces, el número total de formatos de direcciones será numer_of_countries multiplicado por el número de formatos de direcciones en este país … Se puede hacer con diferentes tablas, pero será un trabajo horrible de hacer.

Sé que este es un tema muy antiguo que ya está respondido, pero pensé que también pondría mi granito de arena. Todo depende de cuáles sean los objectives de su proyecto y cómo espera que los usuarios objective ingresen las direcciones. La sugerencia de Ben le permitirá analizar direcciones con precisión, pero por otro lado podría hacer que el proceso de ingreso de datos del usuario sea más largo (y posiblemente más frustrante). La sugerencia de Stephen Wrighton es más simple, y podría ser más fácil para los usuarios ingresar direcciones como resultado.

También he visto algunos modelos que simplemente tenían una columna de “Dirección” que capturaría un número de calle, tipo, nombre de calle, número de unidad / apartamento típico, etc., todo en una columna, manteniendo la ciudad, el país, la región, etc. dentro de otras columnas. Similar al modelo de Stephen, excepto Address1, Address2 y Address3 todos consolidados en una columna.

Mi opinión es que los modelos más flexibles tienden a ser los menos restrictivos, dependiendo de su interpretación de flexible.

Yo uso https://github.com/commerceguys/addressing library para formatear direcciones internacionales y usan estos elementos:

 Country Administrative area Locality (City) Dependent Locality (in: BR, CN, IR, MY, MX, NZ, PH, KR, ZA, TH) Postal code Sorting code Address line 1 Address line 2 Organization Recipient 

Esto no ayuda si quiere analizar la calle (nombre, número de casa, …).

Por cierto. si está buscando una lista de países en varios idiomas: https://github.com/umpirsky/country-list

    Intereting Posts