292 lines
11 KiB
SQL
292 lines
11 KiB
SQL
-- ============================================================
|
|
-- Materialized view : reporting.mv_location_hierarchy
|
|
-- Scope : toutes les localisations actives de tous les types,
|
|
-- avec résolution de la hiérarchie (parent → root).
|
|
-- Refresh : via management command refresh_reporting_views (daily)
|
|
--
|
|
-- Clé de jointure avec mv_interventions :
|
|
-- mv_interventions.loc_content_type_id = mv_location_hierarchy.content_type_id
|
|
-- mv_interventions.loc_object_id = mv_location_hierarchy.object_id
|
|
--
|
|
-- Types de localisation couverts :
|
|
-- trafficlightintersection (assets_trafficlightintersection)
|
|
-- structurelocation (assets_structurelocation) — groupé par ouvrage
|
|
-- itslocation (assets_itslocation)
|
|
-- naturelocation (assets_naturelocation)
|
|
-- publiclightingstreet (assets_publiclightingstreet)
|
|
-- cleanlocation (assets_cleanlocation)
|
|
-- controlcenterlocation (assets_controlcenterlocation)
|
|
-- signstreet (sign_signstreet)
|
|
-- ============================================================
|
|
|
|
DROP MATERIALIZED VIEW IF EXISTS reporting.mv_location_hierarchy;
|
|
|
|
CREATE MATERIALIZED VIEW reporting.mv_location_hierarchy AS
|
|
WITH RECURSIVE
|
|
|
|
-- ── Résolution des content_type IDs (une seule fois) ───────────────────
|
|
ct (ct_id, model) AS (
|
|
SELECT id AS ct_id, model
|
|
FROM django_content_type
|
|
WHERE (app_label = 'assets' AND model IN (
|
|
'trafficlightintersection',
|
|
'structurelocation',
|
|
'itslocation',
|
|
'naturelocation',
|
|
'publiclightingstreet',
|
|
'cleanlocation',
|
|
'controlcenterlocation'))
|
|
OR (app_label = 'sign' AND model = 'signstreet')
|
|
),
|
|
|
|
-- ── Hiérarchie récursive : ITS Locations ───────────────────────────────
|
|
its_root (id, root_id) AS (
|
|
-- Racines : localisations sans parent
|
|
SELECT id, id AS root_id
|
|
FROM assets_itslocation
|
|
WHERE parent_location_id IS NULL
|
|
-- Enfants : on remonte jusqu'à la racine
|
|
UNION ALL
|
|
SELECT child.id, parent.root_id
|
|
FROM assets_itslocation child
|
|
JOIN its_root parent ON parent.id = child.parent_location_id
|
|
),
|
|
|
|
-- ── Hiérarchie récursive : Nature Locations ────────────────────────────
|
|
nature_root (id, root_id) AS (
|
|
SELECT id, id AS root_id
|
|
FROM assets_naturelocation
|
|
WHERE parent_location_id IS NULL
|
|
UNION ALL
|
|
SELECT child.id, parent.root_id
|
|
FROM assets_naturelocation child
|
|
JOIN nature_root parent ON parent.id = child.parent_location_id
|
|
),
|
|
|
|
-- ── Hiérarchie récursive : Control Center Locations ───────────────────
|
|
cc_root (id, root_id) AS (
|
|
SELECT id, id AS root_id
|
|
FROM assets_controlcenterlocation
|
|
WHERE parent_location_id IS NULL
|
|
UNION ALL
|
|
SELECT child.id, parent.root_id
|
|
FROM assets_controlcenterlocation child
|
|
JOIN cc_root parent ON parent.id = child.parent_location_id
|
|
)
|
|
|
|
-- ── Traffic Light Intersections ─────────────────────────────────────────────
|
|
-- Niveau de regroupement : l'intersection elle-même (ou son maître si défini).
|
|
SELECT
|
|
(SELECT ct_id FROM ct WHERE model = 'trafficlightintersection') AS content_type_id,
|
|
tli.id AS object_id,
|
|
'trafficlightintersection' AS location_type,
|
|
tli.code,
|
|
tli.name_fr,
|
|
tli.name_nl,
|
|
tli.lon,
|
|
tli.lat,
|
|
-- Parent : intersection maître (peut être NULL)
|
|
(SELECT ct_id FROM ct WHERE model = 'trafficlightintersection') AS parent_content_type_id,
|
|
tli.master_id AS parent_object_id,
|
|
-- Root : soi-même (les intersections sont le niveau atomique de regroupement)
|
|
(SELECT ct_id FROM ct WHERE model = 'trafficlightintersection') AS root_content_type_id,
|
|
tli.id AS root_object_id,
|
|
tli.code AS root_code,
|
|
tli.name_fr AS root_name_fr,
|
|
tli.name_nl AS root_name_nl,
|
|
mun.name_fr AS municipality_name_fr,
|
|
mun.name_nl AS municipality_name_nl
|
|
FROM assets_trafficlightintersection tli
|
|
LEFT JOIN common_municipality mun ON mun.id = tli.municipality_id
|
|
|
|
UNION ALL
|
|
|
|
-- ── Structure Locations ─────────────────────────────────────────────────────
|
|
-- Regroupement par ouvrage (Structure) ; root = localisation principale de l'ouvrage.
|
|
SELECT
|
|
(SELECT ct_id FROM ct WHERE model = 'structurelocation'),
|
|
sl.id,
|
|
'structurelocation',
|
|
sl.code,
|
|
sl.name_fr,
|
|
sl.name_nl,
|
|
sl.lon,
|
|
sl.lat,
|
|
(SELECT ct_id FROM ct WHERE model = 'structurelocation'),
|
|
sl.parent_location_id,
|
|
(SELECT ct_id FROM ct WHERE model = 'structurelocation'),
|
|
COALESCE(
|
|
(SELECT id FROM assets_structurelocation
|
|
WHERE structure_id = sl.structure_id
|
|
AND is_main_location = TRUE
|
|
LIMIT 1),
|
|
sl.id
|
|
) AS root_object_id,
|
|
COALESCE(s.code, sl.code) AS root_code,
|
|
COALESCE(s.name_fr, sl.name_fr) AS root_name_fr,
|
|
COALESCE(s.name_nl, sl.name_nl) AS root_name_nl,
|
|
NULL::VARCHAR AS municipality_name_fr,
|
|
NULL::VARCHAR AS municipality_name_nl
|
|
FROM assets_structurelocation sl
|
|
LEFT JOIN assets_structure s ON s.id = sl.structure_id
|
|
|
|
UNION ALL
|
|
|
|
-- ── ITS Locations ────────────────────────────────────────────────────────────
|
|
SELECT
|
|
(SELECT ct_id FROM ct WHERE model = 'itslocation'),
|
|
il.id,
|
|
'itslocation',
|
|
il.code,
|
|
il.name_fr,
|
|
il.name_nl,
|
|
il.lon,
|
|
il.lat,
|
|
(SELECT ct_id FROM ct WHERE model = 'itslocation'),
|
|
il.parent_location_id,
|
|
(SELECT ct_id FROM ct WHERE model = 'itslocation'),
|
|
ir.root_id,
|
|
root_il.code,
|
|
root_il.name_fr,
|
|
root_il.name_nl,
|
|
NULL::VARCHAR,
|
|
NULL::VARCHAR
|
|
FROM assets_itslocation il
|
|
JOIN its_root ir ON ir.id = il.id
|
|
JOIN assets_itslocation root_il ON root_il.id = ir.root_id
|
|
|
|
UNION ALL
|
|
|
|
-- ── Nature Locations ─────────────────────────────────────────────────────────
|
|
SELECT
|
|
(SELECT ct_id FROM ct WHERE model = 'naturelocation'),
|
|
nl.id,
|
|
'naturelocation',
|
|
nl.code,
|
|
nl.name_fr,
|
|
nl.name_nl,
|
|
nl.lon,
|
|
nl.lat,
|
|
(SELECT ct_id FROM ct WHERE model = 'naturelocation'),
|
|
nl.parent_location_id,
|
|
(SELECT ct_id FROM ct WHERE model = 'naturelocation'),
|
|
nr.root_id,
|
|
root_nl.code,
|
|
root_nl.name_fr,
|
|
root_nl.name_nl,
|
|
mun.name_fr,
|
|
mun.name_nl
|
|
FROM assets_naturelocation nl
|
|
JOIN nature_root nr ON nr.id = nl.id
|
|
JOIN assets_naturelocation root_nl ON root_nl.id = nr.root_id
|
|
LEFT JOIN common_municipality mun ON mun.id = nl.municipality_id
|
|
|
|
UNION ALL
|
|
|
|
-- ── Public Lighting Streets ──────────────────────────────────────────────────
|
|
SELECT
|
|
(SELECT ct_id FROM ct WHERE model = 'publiclightingstreet'),
|
|
pls.id,
|
|
'publiclightingstreet',
|
|
pls.code,
|
|
pls.name_fr,
|
|
pls.name_nl,
|
|
pls.lon,
|
|
pls.lat,
|
|
NULL::INTEGER,
|
|
NULL::INTEGER,
|
|
(SELECT ct_id FROM ct WHERE model = 'publiclightingstreet'),
|
|
pls.id,
|
|
pls.code,
|
|
pls.name_fr,
|
|
pls.name_nl,
|
|
mun.name_fr,
|
|
mun.name_nl
|
|
FROM assets_publiclightingstreet pls
|
|
LEFT JOIN common_municipality mun ON mun.id = pls.municipality_id
|
|
|
|
UNION ALL
|
|
|
|
-- ── Clean Locations ───────────────────────────────────────────────────────────
|
|
SELECT
|
|
(SELECT ct_id FROM ct WHERE model = 'cleanlocation'),
|
|
cl.id,
|
|
'cleanlocation',
|
|
cl.code,
|
|
cl.name_fr,
|
|
cl.name_nl,
|
|
cl.lon,
|
|
cl.lat,
|
|
NULL::INTEGER,
|
|
NULL::INTEGER,
|
|
(SELECT ct_id FROM ct WHERE model = 'cleanlocation'),
|
|
cl.id,
|
|
cl.code,
|
|
cl.name_fr,
|
|
cl.name_nl,
|
|
mun.name_fr,
|
|
mun.name_nl
|
|
FROM assets_cleanlocation cl
|
|
LEFT JOIN common_municipality mun ON mun.id = cl.municipality_id
|
|
|
|
UNION ALL
|
|
|
|
-- ── Control Center Locations ─────────────────────────────────────────────────
|
|
SELECT
|
|
(SELECT ct_id FROM ct WHERE model = 'controlcenterlocation'),
|
|
ccl.id,
|
|
'controlcenterlocation',
|
|
ccl.code,
|
|
ccl.name_fr,
|
|
ccl.name_nl,
|
|
ccl.lon,
|
|
ccl.lat,
|
|
(SELECT ct_id FROM ct WHERE model = 'controlcenterlocation'),
|
|
ccl.parent_location_id,
|
|
(SELECT ct_id FROM ct WHERE model = 'controlcenterlocation'),
|
|
ccr.root_id,
|
|
root_ccl.code,
|
|
root_ccl.name_fr,
|
|
root_ccl.name_nl,
|
|
NULL::VARCHAR,
|
|
NULL::VARCHAR
|
|
FROM assets_controlcenterlocation ccl
|
|
JOIN cc_root ccr ON ccr.id = ccl.id
|
|
JOIN assets_controlcenterlocation root_ccl ON root_ccl.id = ccr.root_id
|
|
|
|
UNION ALL
|
|
|
|
-- ── Sign Streets ─────────────────────────────────────────────────────────────
|
|
SELECT
|
|
(SELECT ct_id FROM ct WHERE model = 'signstreet'),
|
|
ss.id,
|
|
'signstreet',
|
|
ss.code,
|
|
ss.name_fr,
|
|
ss.name_nl,
|
|
ss.lon,
|
|
ss.lat,
|
|
NULL::INTEGER,
|
|
NULL::INTEGER,
|
|
(SELECT ct_id FROM ct WHERE model = 'signstreet'),
|
|
ss.id,
|
|
ss.code,
|
|
ss.name_fr,
|
|
ss.name_nl,
|
|
mun.name_fr,
|
|
mun.name_nl
|
|
FROM sign_signstreet ss
|
|
LEFT JOIN common_municipality mun ON mun.id = ss.municipality_id
|
|
|
|
WITH DATA;
|
|
|
|
-- ── Index unique requis pour REFRESH MATERIALIZED VIEW CONCURRENTLY ─────────
|
|
CREATE UNIQUE INDEX reporting_mv_location_hierarchy_pk
|
|
ON reporting.mv_location_hierarchy (content_type_id, object_id);
|
|
|
|
-- ── Index opérationnels ──────────────────────────────────────────────────────
|
|
CREATE INDEX reporting_mv_location_hierarchy_type
|
|
ON reporting.mv_location_hierarchy (location_type);
|
|
|
|
CREATE INDEX reporting_mv_location_hierarchy_root
|
|
ON reporting.mv_location_hierarchy (root_content_type_id, root_object_id);
|