Vous n'êtes pas identifié(e).
Pages : 1
Bonjour,
Je souhaiterai avoir des pistes de scripts pour la rédaction d'une requête qui me permettrait de versionner les lignes d'une table.
Je m'explique.
J'ai une table X :
Numéro Date Début Fin
001 20/12/2020 1 2
001 20/12/2020 4 5
001 20/12/2020 7 8
001 21/12/2020 3 4
001 21/12/2020 6 7
001 21/12/2020 9 10
001 22/12/2020 1 2
001 22/12/2020 4 5
001 22/12/2020 7 8
Théoriquement, je suis sensé avec les mêmes trio de valeurs de départ et d'arrivée pour chaque jour. Or ce n'est pas le cas dans mon contexte.
Pour cela je souhaiterai versionner les numéros pour obtenir la table Y suivante :
Numéro Date Début Fin Variation
001 20/12/2020 1 2 Version 1
001 20/12/2020 4 5 Version 1
001 20/12/2020 7 8 Version 1
001 21/12/2020 3 4 Version 2
001 21/12/2020 6 7 Version 2
001 21/12/2020 9 10 Version 2
001 22/12/2020 1 2 Version 1
001 22/12/2020 4 5 Version 1
001 22/12/2020 7 8 Version 1
Pourriez vous m'éclairer sur la démarche à suivre ?
Merci à vous.
Hors ligne
Voulez-vous modifier la table afin d'avoir l'information de version, ou la calculer dynamiquement à l'aide d'une requête quand vous avez besoin de l'information ?
Julien.
https://rjuju.github.io/
Hors ligne
Merci pour votre réponse.
Je souhaiterai modifier la table.
Hors ligne
Peut-être que vous devriez expliquer la logique qui permet d'obtenir la colonne "Variation" parce qu'en regardant juste l'exemple ça n'a rien d'évident.
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Très bien.
Chaque numéro est composé d'un triplet de lignes (arrivée, départ) qui est sensé être identique d'un jour à l'autre :
Exemple :
Le 20/01/2020, pour le numéro 003, j'ai trois lignes
départ arrivee
1 2
3 4
5 9
Le 21/01/2020, pour ce même numéro,
départ arrivee
1 2
3 4
5 9
Etc. pour chaque jour.
Or, il arrive quelques jours dans l'année, ce triplet de lignes soit différent d'un jour à l'autre :
Le 14/06/2020, pour ce même numéro,
départ arrivee
1 2
3 4
7 9
Pour cela, si pour un même numéro, j'ai des triplets différents (au moins une valeur différente) d'un jour à l'autre, alors je souhaiterai versionner mes numéros :
20/01/2020
départ arrivee version
1 2 v1
3 4 v1
5 9 v1
21/01/2020
départ arrivee
1 2 v1
3 4 v1
5 9 v1
14/06/2020
départ arrivee
1 2 v2
3 4 v2
7 9 v2
J'espère avoir été suffisamment clair.
Merci à vous
Hors ligne
Donc le triplet c'est 3 lignes, et ça c'est compliqué du point de vue relationnel, qui ne gère pas de relations inter-lignes en-dehors des contraintes d'unicité.
Pour pouvoir dire qu'un groupe de 3 lignes est égal ou pas à une autre groupe de 3 lignes, et ça sur toute la longueur de la table, typiquement il faudrait les aggréger pour qu'un triplet devienne une seule ligne.
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Du coup, on aura une ligne par numéro et par jour, avec par un exemple, un nouveau champ qui concatène toutes les valeurs arrivées et départs :
numero date valeurs_concat
001 20/01/2020 1-2-3-4-5-9
001 21/01/2020 1-2-3-4-5-9
001 14/06/2020 1-2-3-4-7-9
Est-ce bien cela ?
Si oui, comment composer une telle table ?
Merci à vous
Hors ligne
Si ce nombre 3 est fixé par le modèle, ça pourrait être plus simplement des colonnes debut1,fin1,debut2,fin2,debut3,fin3.
Si on considère que le nombre est variable, ça pourrait être un tableau, à une ou deux dimensions.
Par exemple cette requête regroupe en tableau à 2 dimensions:
select numero,date, array_agg( array[debut,fin] order by debut) as tableau
from NomDeTable
group by numero,date;
Après la question du versionnage doit pouvoir être abordée un classement inter-ligne par le tableau.
La requête ci-dessous ne devrait pas être loin de ce qui est cherché:
select liste.*, dense_rank() over (partition by numero order by tableau)
from (select numero,date, array_agg( array[debut,fin] order by debut) as tableau from NomDeTable group by numero,date) AS liste
order by numero, date;
Dernière modification par dverite (15/05/2020 16:28:18)
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Cher dverite,
Permet moi de répondre avec simpliciter :
Merci.
J'ai appliqué ta logique d'implémentation à mon cas et il marche à merveille. J'obtiens satisfaction totale.
Merci pour ce professionnalisme.
Hors ligne
Par contre, j'ai une requête à faire.
Le script fonctionne bien sauf pour un élément qui est important à prendre en compte.
Lorsqu'il incrémente les différentes versions, il les classe par tab_temp.
=> Or, il faudrait que l'ordre (et uniquement l'ordre) d'incrémentation se fasse par date.
Actuellement :
date départ arrivee version
20/01 2 3 v2
20/01 3 5 v2
20/01 5 9 v2
21/01 2 3 v1
21/01 3 5 v1
21/01 5 9 v1
Ma cible :
date départ arrivee version
20/01 2 3 v1
20/01 3 5 v1
20/01 5 9 v1
21/01 2 3 v2
21/01 3 5 v2
21/01 5 9 v2
Hors ligne
Hmm. Le tri par le tableau n'est pas fait pour trier mais pour générer un nouveau rang (dense_rank()) dès que la valeur change dans la même partition. On ne peut pas changer ce tri sans que ça invalide complètement l'idée qui fonde cette requête.
Mais on doit pouvoir influer dans le sens voulu en triant par date la sous-requête "liste", autrement dit:
select liste.*, dense_rank() over (partition by numero order by tableau)
from (select numero,date, array_agg( array[debut,fin] order by debut) as tableau
from NomDeTable group by numero,date ORDER BY date) AS liste
order by numero, date;
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Dverite,
J'ai essayé mais hélas, j'ai un classement qui ne correspond pas à un classement par date.
C'est compliqué car il faut "influencer" le champ tableau.
Je ne sais pas si une autre solution peut être possible.
Hors ligne
Je ne sais pas ce qui diffère du résultat attendu.
J'ai mis un test sur db-fiddle ici: https://www.db-fiddle.com/f/o13bBV4hjLWwJYjSiSDLRa/0
Si vous voulez, vous pouvez changer les données de la table avec une série de valeurs qui met en évidence le problème.
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
J'ai mis à jour le db-fiddle.
Tu verras que j'y ai mis un cas précis qui te montrera ma problématique.
Hors ligne
Il faudrait reposter l'URL car ça ne doit pas être la même, c'est versionné.
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Voici le lien : https://www.db-fiddle.com/f/o13bBV4hjLWwJYjSiSDLRa/2
Hors ligne
Effectivement la solution "simple" pour le tri par date ne semble pas faire l'affaire.
Voici une solution différente qui ajoute un étage de requête avec un regroupement intermédiaire par date:
select numero,tableau,unnest(dates) as d,version from
(select numero,tableau, array_agg(date) as dates, dense_rank() over (partition by numero order by min(date)) as version
from (select numero,date, array_agg( array[debut,fin] order by debut) as tableau from testdata group by numero,date) AS liste
group by numero,tableau) s
order by numero,d;
@DanielVerite
http://blog-postgresql.verite.pro/
Hors ligne
Pages : 1