PostgreSQL La base de donnees la plus sophistiquee au monde.

Forums PostgreSQL.fr

Le forum officiel de la communauté francophone de PostgreSQL

Vous n'êtes pas identifié(e).

#1 10/01/2012 23:26:35

palex
Membre

Update En meme temps qu'un select

Bonjour

j'ai une demande un peu particulière afin de gérer une liste d'affichage sur une application.

je dois gérer le fait que sur la grille en question l'utilisateur puisse trier ses infos sur tel ou tel colonne et que s'il rajoute un produit dans la liste, le produit s'ajoute en fin de liste sans tenir compte du tri appliqué.
pour cela j'ai ajouté dans ma table un champs qui me sers pour connaitre l'ordre d'affichage, du coup à chaque affichage de ma grille je fais toujours un order by ordreDuTri, du coup dès que je clique sur un en tete de colonne j'execute ma requete sur le tri en question et je mets à jour ma colonne ordre de tri et enfin pour afficher le rendu final je recupere les infos en ayant toujours le order by ordreDeTri du coup les infos sont bien affiché dans le bonne ordre vu que je viens de mettre à jour ce champs dans l'ordre ASC.

Mon souci c'est le fait de jouer la premiere requete sur le tri selectionné et de mettre à jour mon champs ordreDeTri.

Exemple si j'ai 300 produits dans ma grille que je veux trier sur le libelle, je recupère donc cette liste trié sur le libellé et derriere je met à jour le champs ordreDeTri pour que l'affichage final soit ok, du coup si je rajoute un produit dans la liste, je luis met un max(ordreDeTri)+1 et vu que je tri ma liste toujours en fonction de ce champs et bien il se retrouve en fin de liste comme il le faut.
mais ce qui m'embete c'est le fait de recupérer mes 300 lignes dans un ordre et de faire derrière 300 update en ayant uniquement changé le champs ordreDeTri

du coup j'ai dans mon code:

List<Object> lst = monDao.getMyList();
int ordreDeTri = 0;
for(Object obj : lst){
 obj.setOrdreDeTri(ordreDeTri++);
 monDao.saveOrUpdate(obj);
}

donc si lst contient 300 objets j'ai 300updates qui passe en base.

j'aimerais donc savoir s'il y a un moyen au moment d'envoyer ma requete select de faire l'update directement en fonction du resultset donc envoyer le select et mettre  à jour le champs ordreDeTri directement sans avoir a faire les 300requetes pas la suite.

la demande n'est pas simple à expliquer, j'espère avoir été clair smile
n'hésitez pas à me dire si vous n'avez pas compris j'essaierai d'être plus clair.

merci beaucoup

Hors ligne

#2 11/01/2012 01:02:05

gleu
Administrateur

Re : Update En meme temps qu'un select

la demande n'est pas simple à expliquer, j'espère avoir été clair

C'est clair que c'est pas clair. J'ai très peu que vous partiez sur une mauvaise piste. Vous ajoutez dans votre table une colonne pour préciser le tri. Sans même parler de la fragmentation que cela va générer dans vos tables, comment voulez-vous que cela puisse fonctionner si deux postes veulent faire un tri ? Ils vont tous les deux écrire dans la même colonne et du coup, les valeurs de cette colonnes n'auront plus aucun sens. Et puis, disons que je sois seul à utiliser cette table, je fais un tri, puis un deuxième puis un troisième et pouf, en trois tri j'ai multiplié la taille de ma table par quatre. Plutôt impressionnant smile

Bref, le peu que j'en ai compris me laisse craindre le pire.

Essayez plutôt d'expliquer ce que vous voulez obtenir au final.


Guillaume.

Hors ligne

#3 11/01/2012 11:00:12

palex
Membre

Re : Update En meme temps qu'un select

bonjour

il s'agit d'une application ou une personne accède à son compte toute seule donc pas de souci de concurrence sur la table, chaque ligne possède un discriminant pour un compte.

Et après un tri, la taille n'est pas multiplié j'ai simplement parlé d'un update d'une colonne donc si j'ai 300 lignes j'en aurais toujours 300 après simplement les 300 aurons été mise à jour

exemple si dans la base j'ai

libelle | reference | ordreDeTri
CCC        5                   0
AAA         6                   1

lors de l'affichage je me base sur ordreDeTri pour afficher ma liste

si je tri ma liste par libelle cela va récupérer la liste trié par libellé donc une premiere requete de type:

select * from matable order by libelle;
ensuite le code qui se trouve dans ma question plus haut avec la boucle sur chaque ligne pour mettre à jour l'ordre

enfin dans la base j'ai uniquement changé la colonne ordreDeTri

libelle | reference | ordreDeTri
CCC        5                   1
AAA         6                   0

si j'ajoute une ligne BBB, meme si ma grille reste trié par libellé, cette ligne va s'ajouter à la fin

libelle | reference | ordreDeTri
CCC        5                   1
AAA         6                   0
BBB         7                   2

car lors de l'affichage de ma grille il y a toujours le order by ordreDeTri donc
AAA
CCC
BBB

si enfin je retri par libelle cela va donner:

libelle | reference | ordreDeTri
CCC        5                   2
AAA         6                   0
BBB         7                   1

je suis d'accord que sur certain poins ca ne parrait pas logique mais il s'agit d'une demande client très demandé donc pas le choix de la gérer comme cela

apres peu importe la demande, moi ce que j'aimerais eviter c'est la boucle qui realise l'update sur ordreDeTri, je voudrais lors de l'envoi de la requete :

select * from matable order by libelle;

pouvoir mettre à jour mon champs ordreDeTri à la volé car le résultat qui m'est envoyé est l'odre exact dans lequel je vais mettre à jour la colonne ordreDeTri donc pourquoi avoir besoin de récupérer le résultat pour faire un update que je pourrais surement faire directement coté postgres donc éviter du transfert réseau et surtout N update.

est ce plus clair? smile

merci

Hors ligne

#4 11/01/2012 13:26:22

palex
Membre

Re : Update En meme temps qu'un select

j'ai peut etre trouvé ma reponse:

create TEMP TABLE tri (id bigint , nouvelordre integer) ;
INSERT INTO tri select id,row_number(*) over(order by macolonne) from matable where macondition = 1 order by macolonne;
UPDATE matable set ordredutri = (select nouvelordre from tri t where t.id = matable.id);
drop table tri

4 requetes au lieu de 300 et aucun transfert réseau.

s'il existe mieux je suis prenneur smile

Hors ligne

#5 11/01/2012 14:24:15

dverite
Membre

Re : Update En meme temps qu'un select

Pourquoi passer par la base pour retrier une liste qui est déjà chargée dans une appli? Les composants d'affichage du genre grille ou liste ont généralement leurs propres méthodes de tri en mémoire par une colonne, visible ou non.
Par ailleurs sil y a 2 utilisateurs simultanés et qu'ils doivent voir un tri différent, l'avoir dans une colonne de la table ne peut pas convenir.

Hors ligne

#6 11/01/2012 15:30:32

palex
Membre

Re : Update En meme temps qu'un select

il ne s'agit malheureusement pas d'une grille mémoire, qui l'était d'ailleurs avant et pour laquelle le probleme que je rencontre aujourd hui n'étais pas. et aujourd hui cette grille devient persistente à chaque modification pour ne rien perdre car il s'agit d'une table longue à construire et si pour une raison X ou Y l'appli venait à s'arretter ou le navigateur crashé tout serait perdu, d'ou la demande de la rendre persistente. Mais si on veut garder certaine règle métier (certe pas forcément toujours cohérente mais très utilisé par les cliens) je n'ai pas le choix de faire comme cela.

En ce qui concerne les 2 utilisateurs simultanés, comme je l'ai précisé chaque utilisateur possède sont propre compte et ses propres données il y un champs discriminant sur chacune des lignes et un seul utilisateur n'a le droit de se connecter qu'une seule et unique fois à l'application donc aucun problème d'accès concurrentiel, et vu qu il s'agit d'une grille de passage de commande, je doute fort que 2 utilisateurs s'amuse à se connecter et à faire n'importe quoi avec si cela était permis smile

la demande initial était de pouvoir trier la liste des produits commandé et si la personne en ajoute dans la grille ils doivent êtres ajoutés à la fin sans tenir compte du tri précédemment sélectionné car beaucoup de client se sont plein que lors de l'ajout de plusieurs produits en meme temps, si la personne avait trié par ordre alphabétique, le produit commencant par la lettre A serait sur la premiere page, ceux par V sur la 20eme etc...(ce qui parrait logique si on tien compte du tri) d'ou l utilité de les avoirs en fin de liste systématiquement pour les retrouver rapidement, et les clients veulent garder l'ordre du tri des lignes précédente.
voila pourquoi je n'ai pas d'autre choix.

je comprends tout a fait vos remarques sur les accès concurrentiel et autres mais dans mon cas pas de souci la dessus. si j'en suis arrivé là c'est vraiment apres avoir retourné le truc dans tous les sens. smile

j'attends la version 9.2 de postgres pour pouvoir faire les 2 premiers requetes en 1 seule (create table ... as select ....) smile

Hors ligne

#7 11/01/2012 17:07:35

palex
Membre

Re : Update En meme temps qu'un select

bon j'ai finalement implémenté cela dans l'application et tout fonctionne parfaitement.on peu passer le sujet en résolu pour ma part
merci à vous

Dernière modification par palex (11/01/2012 17:08:01)

Hors ligne

Pied de page des forums