| 262 | == Distance source (Parcours source) |
| 263 | {{{ |
| 264 | #!sql |
| 265 | -- script de calcul des distances sources |
| 266 | set search_path to rht,public; |
| 267 | select cast(ltree2text(subltree(chemin,0,1)) as integer) from rht_topology limit 10 |
| 268 | /* |
| 269 | AJOUT D'UN INDEX |
| 270 | ltree supports several types of indexes that can speed up the indicated operators: |
| 271 | B-tree index over ltree: <, <=, =, >=, > |
| 272 | GiST index over ltree: <, <=, =, >=, >, @>, <@, @, ~, ? |
| 273 | */ |
| 274 | CREATE INDEX chemin_btee_index ON rht.rht_topology USING btree(chemin); --27688 ms |
| 275 | VACUUM ANALYSE rht.rht_topology; |
| 276 | CREATE INDEX chemin_gist_index ON rht.rht_topology USING GIST (chemin); -- fait planter mon serveur.... |
| 277 | SELECT * from rht.rht_topology where chemin <@ '212340'; -- tronçon source de la Vilaine -- 2360 |
| 278 | SELECT chemin from rht.rht_topology where chemin <@ '212340' limit 1 |
| 279 | -- La distance source est la distance mer maximale de tous les chemins possibles en ne prenant que le dernier tronçon du chemin. |
| 280 | Select max(dmer) from rht.rht_topology where id_drain in ( |
| 281 | Select cast(ltree2text(subpath(chemin, -1, 1))as integer) as chenin_id_drain from rht.rht_topology where chemin ~ '*.212340.*'); |
| 282 | -- travail sur les noeuds source et le recalcul des distances mer et source (voir fichier doc joint) |
| 283 | -- en pratique les distances sont calculées a partir du milieu de chaque tronçon, elles prennent par contre toute la distance des tronçons autre que le tronçon considéré. |
| 284 | |
| 285 | alter table rht.rht_topology add column noeudsource boolean default FALSE; |
| 286 | -- identification des noeuds source |
| 287 | update rht.rht_topology set noeudsource=TRUE where id_drain in ( |
| 288 | select id_drain from rht.rht_topology except ( |
| 289 | select rt2.id_drain from rht.rht_topology rt1 join rht.rht_topology rt2 on rt1.nextdownid=rt2.id_drain) |
| 290 | );-- 57533 |
| 291 | update rht.rht_topology set dmer=dmer+length/2;-- 114600 |
| 292 | alter table rht.rht_topology add column dsource numeric; |
| 293 | update rht.rht_topology set dsource=length/2 where noeudsource;-- 57533 |
| 294 | -- voir schéma pour explications |
| 295 | |
| 296 | |
| 297 | DROP FUNCTION IF EXISTS rht.distance_source(); |
| 298 | |
| 299 | CREATE OR REPLACE FUNCTION rht.distance_source(min integer, max integer) RETURNS integer AS $$ |
| 300 | DECLARE |
| 301 | ligne integer; |
| 302 | nbligne integer; |
| 303 | id_drains record; |
| 304 | BEGIN |
| 305 | ligne:=1; |
| 306 | DROP TABLE IF EXISTS sousselection; |
| 307 | DROP sequence IF EXISTS seq; |
| 308 | CREATE sequence seq; |
| 309 | EXECUTE 'create temporary table sousselection as SELECT id_drain, nextval(''seq'') as num FROM (SELECT * FROM rht.rht_topology WHERE noeudsource=FALSE ORDER BY id_drain) as sub WHERE id_drain >='|| min || ' AND id_drain<='||max ; |
| 310 | SELECT COUNT(*) FROM sousselection INTO nbligne; |
| 311 | WHILE ligne <=nbligne LOOP |
| 312 | -- pour vérification décommenter ensuite |
| 313 | SELECT * from sousselection where num=ligne INTO id_drains; |
| 314 | RAISE NOTICE 'distance_source for %', quote_ident(CAST(id_drains.id_drain as text)); |
| 315 | EXECUTE 'INSERT INTO rht.distance_source SELECT '||id_drains.id_drain||', MAX(dmer+length/2) as dmer FROM rht.rht_topology WHERE id_drain IN ( |
| 316 | SELECT CAST(ltree2text(subpath(chemin, -1, 1))as integer) FROM rht.rht_topology where chemin ~ ''*.'|| |
| 317 | id_drains.id_drain |
| 318 | || '.*'' )'; |
| 319 | ligne=ligne+1; |
| 320 | END LOOP; |
| 321 | RETURN ligne; |
| 322 | END; |
| 323 | $$ LANGUAGE plpgsql; |
| 324 | -- lancement de la requête |
| 325 | DROP TABLE IF EXISTS rht.distance_source; |
| 326 | CREATE TABLE rht.distance_source (id_drain integer,distance numeric); |
| 327 | select rht.distance_source(1,50000); |
| 328 | |
| 329 | -- pour essai pour voir ce qui se passe dans la requête |
| 330 | |
| 331 | SELECT 212340, MAX(dmer+length/2) as dmer FROM rht.rht_topology WHERE id_drain IN ( |
| 332 | SELECT CAST(ltree2text(subpath(chemin, -1, 1))as integer) FROM rht.rht_topology where chemin ~ '*.212340.*' ) |
| 333 | -- il faudra enlever la dmer de 212340 |
| 334 | |
| 335 | -- POUR LES LANCEMENTS FINAUX IL A FALLU LANCER UN INDEX ET RAJOUTER UNE CLE PRIMAIRE |
| 336 | Alter table rht.rht_topology add constraint c_pk_id_drain primary key (id_drain); |
| 337 | CREATE INDEX id_drain_index ON rht.rht_topology |
| 338 | USING btree |
| 339 | (id_drain); |
| 340 | |
| 341 | select rht.distance_source(100000,200000); |
| 342 | select rht.distance_source(200001,300000); |
| 343 | select rht.distance_source(300001,400000); |
| 344 | select rht.distance_source(400001,600000); |
| 345 | |
| 346 | -- pour essai pour voir ce qui se passe dans la requête |
| 347 | |
| 348 | SELECT 212340, MAX(dmer+length/2) as dmer FROM rht.rht_topology WHERE id_drain IN ( |
| 349 | SELECT CAST(ltree2text(subpath(chemin, -1, 1))as integer) FROM rht.rht_topology where chemin ~ '*.212340.*' ) |
| 350 | |
| 351 | |
| 352 | select * from rht.rht_topology t join rht.distance_source s on s.id_drain=t.id_drain where distance is null; --323 |
| 353 | |
| 354 | -- il faudra enlever la dmer de 212340 |
| 355 | |
| 356 | -- requête finale pour calculer les distances source (à lancer) |
| 357 | alter table rht.distance_source add column distance_source numeric; |
| 358 | select count(*) from rht.distance_source; --57067 que les noeuds non source |
| 359 | |
| 360 | -- mise à jour des distances source dans la table distance source (il faut encore enlever dmer) |
| 361 | update rht.distance_source d set distance_source = sub.distance_source from ( |
| 362 | select t.id_drain, distance-dmer as distance_source from rht.distance_source s join rht.rht_topology t on s.id_drain=t.id_drain) as sub |
| 363 | where sub.id_drain=d.id_drain; --57067 |
| 364 | |
| 365 | -- copie des valeurs de distance_source dans dsource de la table rht.rht_topology |
| 366 | update rht.rht_topology t set dsource=distance_source |
| 367 | from rht.distance_source d where d.id_drain=t.id_drain; --57067 |
| 368 | |
| 369 | -- mise à jour des distances_source (pour l'instant valeurs = null) pour les noeuds source (pour les derniers c'est la moitié de la longueur du segment) |
| 370 | update rht.rht_topology t set dsource=length/2 where noeudsource; |
| 371 | -- nombre de |
| 372 | select count(*)as count, noeudsource from rht.rht_topology where dsource is null group by noeudsource; |
| 373 | }}} |
| 374 | |
| 375 | |
| 376 | == Utilisation des donnees de parcours == |
| 377 | En pratique nous n'aurons probablement besoin que du noeud le plus amont des parcours comme programmé ci dessus. Mais les scripts ci-dessous pourraient s'avérer utiles. [[BR]] |
| 378 | Ci dessous la fonction utilise les expressions régulières ltree => vecteur => table |
| 379 | |
| 380 | {{{ |
| 381 | #!sql |
| 382 | /* |
| 383 | regexp_split_to_array(string text, pattern text [, flags text ]) regexp_split_to_array('hello world', E'\\s+') {hello,world} |
| 384 | SELECT regexp_split_to_array('hello world', E'\\s+'); |
| 385 | SELECT regexp_split_to_array('hello.world', E'\\.+'); |
| 386 | */ |
| 387 | SELECT regexp_split_to_array(ltree2text(chemin),E'\\.+') from rht.rht_topology where chemin <@ '212340'; |
| 388 | |
| 389 | /* |
| 390 | http://www.pgsql.cz/index.php/PostgreSQL_SQL_Tricks#Array_to_table |
| 391 | SELECT (ARRAY[1,3,4,6,7])[idx.n] FROM generate_series(1,7) idx(n); |
| 392 | CREATE OR REPLACE FUNCTION unpack(anyarray) |
| 393 | RETURNS SETOF anyelement AS $$ |
| 394 | SELECT $1[i] |
| 395 | FROM generate_series(array_lower($1,1), |
| 396 | array_upper($1,1)) g(i); |
| 397 | $$ LANGUAGE sql STRICT IMMUTABLE; |
| 398 | */ |
| 399 | CREATE OR REPLACE FUNCTION unpack(anyarray) |
| 400 | RETURNS SETOF anyelement AS $$ |
| 401 | SELECT $1[i] |
| 402 | FROM generate_series(array_lower($1,1), |
| 403 | array_upper($1,1)) g(i); |
| 404 | $$ LANGUAGE sql STRICT IMMUTABLE; |
| 405 | -- pour convertir un vecteur en table |
| 406 | select unpack(vecteurchemin) from |
| 407 | (SELECT regexp_split_to_array(ltree2text(chemin),E'\\.+') as vecteurchemin from rht.rht_topology where chemin <@ '212340' limit 1) as sub |
| 408 | -- j'avais pas vu il y a déjà une fonction magique unest... |
| 409 | select cast(unnest(vecteurchemin) as integer) as chemin_id_drain from |
| 410 | (SELECT regexp_split_to_array(ltree2text(chemin),E'\\.+') as vecteurchemin from rht.rht_topology where chemin <@ '212340' limit 1) as sub |
| 411 | -- Fonction qui renvoit les identifiants uniques des tronçons en amont d'un ouvrage |
| 412 | |
| 413 | |
| 414 | CREATE OR REPLACE FUNCTION troncons(integer) |
| 415 | RETURNS SETOF integer AS $$ |
| 416 | select cast(unnest(vecteurchemin) as integer) as chemin_id_drain from |
| 417 | (SELECT regexp_split_to_array(ltree2text(chemin),E'\\.+') as vecteurchemin from rht.rht_topology where chemin <@ text2ltree(cast ($1 as text)) limit 1) as sub; |
| 418 | $$ LANGUAGE sql STRICT IMMUTABLE; |
| 419 | |
| 420 | SELECT troncons_amont(212340); -- OK |
| 421 | }}} |
| 422 | |