Tener 2 tablas, "Instituciones" y "Áreas"
Permitir que "Áreas" se vincule consigo mismo, es decir, area_id, parent_area_id
De esta manera, siempre vincula una Institución a un area_id, y luego la lógica interna puede determinar si esa área se considera un Distrito o una Ciudad.
Así que ahora tienes
institutions (
id UNSIGNED INT NOT NULL PK AI,
area_id UNSIGNED INT NOT NULL,
name VARCHAR NOT NULL
)
y
areas (
id UNSIGNED INT NOT NULL PK AI,
parent_area_id UNSIGNED INT NOT NULL DEFAULT 0,
name VARCHAR NOT NULL,
type ENUM('city','district') NOT NULL DEFAULT 'city'
)
El campo areas.type es opcional, pero si desea definirlos como tales, esa puede ser una forma de hacerlo dentro de la base de datos (de lo contrario, suponga que si parent_area_id =0, entonces es una ciudad, de lo contrario es un distrito)
De esta manera, al seleccionar el campo, todo lo que está haciendo es
SELECT *
FROM institutions
INNER JOIN areas
ON areas.id = institutions.area_id
Puede estar 100% seguro de a dónde se vincula la institución area_id, no hay ningún signo de interrogación sobre si ir a la tabla de Distritos o Ciudades, definitivamente irá a la tabla de áreas que a su vez trata Distritos y Ciudades de la misma manera y presenta información en un formato que su interfaz puede interpretar como ciudad o distrito. Opcionalmente, podrías ir un paso más allá si realmente quisieras
SELECT
i.*,
COALESCE(a_parent.id,a_child.id) AS city_id,
COALESCE(a_parent.name,a_child.name) AS city_name
FROM institutions AS i
INNER JOIN areas AS a_child
ON a_child.id = i.area_id
LEFT JOIN areas AS a_parent
ON a_parent.id = a_child.parent_area_id
Que, por ejemplo, siempre devolvería el nombre de la ciudad incluso si la institución estuviera vinculada a un distrito específico dentro de una ciudad