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 Général » Calcul entre 2 dates et valeur null » 18/04/2013 14:58:55

palex
Réponses : 1

bonjour à tous

je dispose de ce jeux de données:

 select  groupeid,datecreationitem from itemagenda where typeitemagenda = 5  and groupeid in(12225,12376)  order by groupeid,datecreationitem ;
 groupeid |  datecreationitem   
----------+---------------------
    12225 | 2013-04-02 00:00:00
    12225 | 2013-04-16 00:00:00
    12225 | 2013-04-30 00:00:00
    12225 | 2013-05-17 00:00:00
    12225 | 2013-06-03 00:00:00
    12376 | 2013-03-27 00:00:00
    12376 | 2013-04-04 00:00:00
    12376 | 2013-04-11 00:00:00
    12376 | 2013-04-18 00:00:00
    12376 | 2013-04-25 00:00:00

groupeId étant un identifiant magasin et datecreationitem étant simplement des dates de livraison

j'ai besoin pour chaque groupeid de calculer le nombre de jour entre la date du jour et la 2eme date de livraison qui est supérieur à la date du jour donc en gros je veux avoir  au final :

1/ Je prends les dates qui sont supérieur à maintenant et ensuite je prend l'indice 2 et je calcul la différence pour avoir le nombre de jour:

select  groupeid,datecreationitem from itemagenda where typeitemagenda = 5  and groupeid in(12225,12376) and datecreationitem > now() order by groupeid,datecreationitem ;
 groupeid |  datecreationitem   
----------+---------------------
    12225 | 2013-04-30 00:00:00
    12225 | 2013-05-17 00:00:00
    12225 | 2013-06-03 00:00:00
    12376 | 2013-04-25 00:00:00
(4 rows)

donc pour le groupeid 12225 cela me donne 2013-05-17 00:00:00 - now() et pour 12376 null - now() (donc rien)

2/pour au final faire cela en une requete voici la requete final que j'ai immaginé:

select  distinct groupeid, nth_value(datecreationitem,2)  over (partition by groupeid  order by datecreationitem) - now()  from itemagenda where typeitemagenda = 5 and datecreationitem > now()  order by groupeid ;

ce qui me retourne ce genre de chose:

groupeid |        ?column?         
----------+-------------------------
    11467 | 32 days 09:07:11.020451
    11467 | 
    11472 | 
    11472 | 21 days 09:07:11.020451
    11640 | 32 days 09:07:11.020451
    11640 | 
    11745 | 
    11745 | 28 days 09:07:11.020451
    11778 | 
    11801 | 
    11801 | 33 days 09:07:11.020451
    12225 | 
    12225 | 28 days 09:07:11.020451
    12344 | 28 days 09:07:11.020451
    12376 | 
    12381 | 

on remarque que les calculs sont correct car pour les 2 groupeid que j'ai pris en exemple au début la requête me ressort bien 28jours pour le 12225 et pour 12376 rien du tout car il n'y a pas de date comme on a pu le voir précédemment.

ma question est pourquoi toute les lignes se retrouve doublé avec une ligne vide? pourquoi par exemple mon groupeid 12225 as 2 lignes?

  12225 | 
  12225 | 28 days 09:07:11.020451

d'ou viens la ligne vide?

je ne demande pas spécialement de solution ou comment vous auriez fait mais je cherche à comprendre le résultat de ma requête, je pensais avoir toute les lignes sans les lignes vide...
je peux m'en sortir avec ce résultat car dans mon code par la suite il me suffit de ne pas tenir compte des lignes vide etc...

merci beaucoup

#2 Général » Probleme utilisation index apres restauration base de données » 15/05/2012 16:34:40

palex
Réponses : 2

bonjour

apres avoir restauré une base de donnée localement, je me suis rendu compte que tout les plans d'executions réalisait des seq_scan, je dois systématiquement faire un reindex afin que les plans d'execution utilise des index_scan,

la commande utilisé est un simple

pg_restore -U postgres fichier.dump

le dump a été fait avec un pg_dump sans options

auriez vous une idée du problème? est ce qu il existe une option pour forcer le reindex ou la creation des indexs lors du restore?

merci

#3 Re : Général » Probleme sur une requete avec distinct et over() » 09/05/2012 09:58:55

bonjour

ce serait effectivement uine solution je pense, en fait comme je le disait precedement on utilise un framework ecri en interne pour générer nos requete de grille et pour le moment il repond à 99% des cas (le 1% etant mon cas à moi qui peut etre resolu en 2 requetes), du coup il faudrait soit faire une evolution du framework pour y inclure la gestion de la clause with soit passer en 2 requetes et le moins couteux et le plus rapide pour le moment est la 2eme solution, si j'ai du temps je ferais evoluer le framework effectivement en attendant "peut etre un jour" un  group by ou distinct dans les fonctions window smile.

merci beaucoup

#4 Re : Général » Probleme sur une requete avec distinct et over() » 07/05/2012 18:37:27

en tout cas merci d'avoir pris le temps de regarder mon problème smile
j'ai quand meme une solution qui est de revenir à 2 requetes(bon si ya moyen d'en faire qu une si tu trouve je suis prenneur quand meme smile), une qui me retourne les données avec le limit qui va bien et la seconde qui me retourne juste les count() pour les meta données sans le limit du coup je n'aurai plus besoin du mot clé over et donc plus de souci de group by ou distinct.

ce qui est dommage c'est que la premiere requete sera identique en terme de jointure et condition donc postgres aura deja fait le travail et je vais devoir lui demander de refaire le meme boulot juste à cause du over qui ne gère pas le disctinct ou group by smile mais apres il y surement d'autre contrainte qui font que cela n'est pas été implémenté smile

#5 Re : Général » Probleme sur une requete avec distinct et over() » 07/05/2012 18:22:17

presque mais du coup le count(distinct codification) from parution ne tient pas compte des conditions de la requete principal, si je rajotue des jointures

SELECT p.libelle, p.codification, p.numero, (SELECT count(DISTINCT codification) FROM parution) FROM parution p
join majointure1 A
join majointure2 B
join majointure3 C
where
A.datesuppression is null
and B.stock > 0
and C.libelle ilike 'toto';

il va falloir que je rajoute dans la sous requete les memes conditions wink
mais petit a petit tu arrive exactement a rejoindre mon probleme car ta prochaine idée sera surement de faire comme j'ai fait au debut avec directement :

SELECT p.libelle, p.codification, p.numero,  count(DISTINCT codification)  FROM parution p ....

mais vu qu il y a un limit afin de gérer la pagination et ne pas retourner au client 2000 lignes alors qu'on en veut uniquement 10, j'ai ajouté le mot clé over() pour ne pas s'areter au limit mais dès que je met le mot clé over(), je n'ai plus le droit d'utiliser distinct ou group by, comme je le disais je pense qu il me faudrait :

count(distinct codification) over() ou alors peut etre un count(codification) over(group by codification)  mais je ne crois pas que ce soit possible smile

#6 Re : Général » Probleme sur une requete avec distinct et over() » 07/05/2012 17:58:55

mais malheureusement meme si cela peut fonctionner, ca risque de compliquer les choses car dans la requete principale j'ai des conditions d'exclusion sur plusieurs jointures et si je ne remet pas les memes jointures et conditions dans le sous requete le count(*) over() me fait un count sur toute la table sans tenir compte des conditions d'exclusions mais en ne tenant compte que de la codification

du coup j'ai realisé un test sur mon appli et je n'ai pas les bon resultat, je pense que de rajouter les jointures dans la sous requetes est mission impossible car il s'agit d'une requete généré par un framework écrit en interne qui ajoute les jointures dynamiquement suivant les colonnes affichées et les critères de recherche défini par l'utilisateur, du coup cela me ressort une requete avec le minimum requis et dans la sous requete j'aipeur que de rajouter trop de jointure me plombe le plan d'execution en plus.

en tout cas merci pour la solution s'était dans la bonne direction wink

#7 Re : Général » Probleme sur une requete avec distinct et over() » 07/05/2012 17:49:54

ha peut etre qu'en rajoutant un over() dans la sous requete ca va peut etre fonctionner  :

SELECT p.libelle, p.codification, p.numero, s.count FROM parution p INNER JOIN (SELECT codification, count(*) over() FROM parution GROUP BY codification) s ON (p.codification = s.codification);

#8 Re : Général » Probleme sur une requete avec distinct et over() » 07/05/2012 17:42:58

si tu fait un insert dans parution :

insert into parution values (tata, 5678, 4);

et que tu rejoue la requete tu auras surement une colonne count avec:

 libelle | codification | numero | count 
---------+--------------+--------+-------
 TOTO    | 3456         |      1 |     2
 TOTO    | 3456         |      2 |     2
 TITI    | 1234         |      6 |     2
 TITI    | 1234         |      7 |     2
 TATA    | 5678         |      4 |     1

je n'ai pas refait le test mais je suppose que le resultat sera celui ci car le count retourne uniquement le nombre de parution pour une codification et dans l'example TOTO => 2 et TITI =2 donc ta requete fonctionne mais c'est juste une question de données je pense non?

et moi j'aimerai avoir pour le cas ci dessus :

 libelle | codification | numero | count 
---------+--------------+--------+-------
 TOTO    | 3456         |      1 |     3
 TOTO    | 3456         |      2 |     3
 TITI    | 1234         |      6 |     3
 TITI    | 1234         |      7 |     3
 TATA    | 5678         |      4 |     3

si tu arrive a avoir le resultat voulu alors la je suis prenneur, je test en tout cas ta solution voir si je peux m'en sortir avec au cas ou
smile

#9 Re : Général » Probleme sur une requete avec distinct et over() » 07/05/2012 11:24:04

merci pour votre réponse,

le partition by me retourne toujours 1, j'avai deja essayé effectivement cette solution mais si j'ai bien compris le partition by va me retourner ce genre de chose:

titre         codification     numero   paritionBy
TOTO    3456                 1            2
TOTO    3456                 2            2
TITI        1234                 4            3
TITI        1234                 5            3
TITI        1234                 6            3
TATA      11111                1             1

mais moi j'aimerais avoir :

TOTO    3456                 1     3
TOTO    3456                 2     3
TITI        1234                 4     3
TITI        1234                 5     3
TITI        1234                 6     3
TATA      11111                1      3

car a l'affichage de mon resultat sur la page j'ai uniquement besoin d'avoir le nombre de titre unique donc dans mon cas j'ai bien 3456, 1234 et 11111 donc 3 titres et dans le tableau qui est affiché en dessous je dois afficher les 6 lignes car elle dispose d'un numero différent, il ne s'agit pas des memes parutions.

on peut tres bien avoir un tele Z numero 1 et un tele Z numero 2 donc je dois afficher les 2 lignes dans ma liste car je peut tres bien modifier soi l'un soi l'autre mais au niveau stat je doit afficher que je dispose d' un seul et unique titre.

je sais que je retourne sur chaque ligne une information identique mais je prefere cela plutot que de rejouer la requete une autre fois derriere sachant que postgres a deja tout le resultat en memoire donc autant qu il fasse le calcul directement.

mon souci c'est de ne pas avoir de count(distinct codification) over() ou alors peut etre un count(codification) over(group by codification) plutot que partition by je pense.

#10 Re : Général » Probleme sur une requete avec distinct et over() » 07/05/2012 09:55:10

j'ai oublié de préciser je suis sur postgres 8.4 en prod et 9.1 sur ma machine, la prod va bientot passer en 9.1 mais peut etre que je devrai trouver une solution pour la 8.4 avant ;(

#11 Général » Probleme sur une requete avec distinct et over() » 07/05/2012 09:51:21

palex
Réponses : 12

bonjour

je dispose de cette requete:

select
        parutionpr1_.codificationTitre as col_1_0_,
	count(parutionpr1_.codificationTitre) over() as col_2_0_
    from
        public.Produit produitpre0_ 
    left outer join
        public.ParutionPresse parutionpr1_ 
            on produitpre0_.fk_parutionpresse=parutionpr1_.id 
            and (
                parutionpr1_.groupeid=20812
            ) 
   
    where
        produitpre0_.discriminator='PRESSE' 
        and (
            produitpre0_.groupeid in (
                20812
            )
        ) 
        and (
            produitpre0_.datesuppression is null
        ) 
    group by
        produitpre0_.id ,
	parutionpr1_.codificationTitre  
    limit 10

le souci c'est que dans la table parutionpresse je peux avoir

libelle  | codification | numero
TOTO    3456                  1
TOTO    3456                  2
TITI        1234                 6
TITI        1234                 7

donc j'aimerai avoir dans mon "count(parutionpr1_.codificationTitre) over() as col_2_0_"   2 car j'ai bien 4 lignes mais qui corresponde a 2 parutions car la codification est identique.

j'ai tenté de faire un "count(distinct parutionpr1_.codificationTitre) over()  mais ce n'est pas autorisé

je ne peut pas réecire la requete avec un with {} comme j'ai pu le voir sur certain sujet sur le net.

existe t il un autre moyen de le faire car sinon je vais etre obligé de séparer ce count dans une autre requete et ca m'embete un peu, car à l'origine cette requete remonte une 10ene de champs et ensuite plusieurs requete étaient jouées pour realiser les count,  j'ai donc ajouté les count() over() dans la meme requete  pour reussir à tout faire en une seule et unique requete, tout fonctionne sauf ce dernier cas.

merci beaucoup

#12 Re : Optimisation » optimisation CAST » 05/04/2012 15:28:58

oui en effet en changeant le type ca va reglé le souci je pense, je vais confirmer cela en realisant un test simple de recherche sur cette colonne avec le type varchar et une autre fois le meme test avec le type text et voir avec l'explain ce qui se passe.

merci

#13 Re : Optimisation » optimisation CAST » 05/04/2012 14:50:28

c'est d'ailleurs suite à une formation Dalibo ou l'ou nous a dis que les cast était très couteux ce qui parrait logique finalement que je me pose la question smile

#14 Re : Optimisation » optimisation CAST » 05/04/2012 14:19:52

en fait je n'ai pas accès direct à la prod mais le dump de prod de la veille est repliqué et je travail sur ce dernier, la premiere fois l'explain ma remonté cela :

 Bitmap Heap Scan on produit produitpre0_  (cost=196.05..208.09 rows=3 width=97) (actual time=17.578..20.224 rows=253 loops=6)
                              Recheck Cond: ((produitpre0_.fk_tva = tva7_.id) AND (produitpre0_.groupeid = 12038))
                             Filter: ((produitpre0_.datemodification >= '2012-03-05 00:00:00'::timestamp without time zone) AND (produitpre0_.typeproduit =
5) AND ((produitpre0_.discriminator)::text = 'PRESSE'::text) AND (produitpre0_.datemodification <= ('now'::text)::date))

et null part je vois l'utilisation de mon index, j'ai donc demandé au dba de regarder si l'index était utilisé en prod et il est toujours à 0. En revanche si je passe le champs en text je vois direct l'utilisation de mon index

        ->  Bitmap Index Scan on idx_produit_discriminator  (cost=0.00..507.77 rows=22780 width=0) (actual time=832.498..832.498
rows=678824 loops=1)
                    Index Cond: (discriminator = 'PRESSE'::text)

#15 Re : Optimisation » optimisation CAST » 05/04/2012 12:40:38

je pense que la fonction qui est appelé est :

 \df texteq
                           List of functions
   Schema   |  Name  | Result data type | Argument data types |  Type  
------------+--------+------------------+---------------------+--------
 pg_catalog | texteq | boolean          | text, text          | normal

#16 Optimisation » optimisation CAST » 05/04/2012 12:35:57

palex
Réponses : 7

bonjour

je viens de voir dans un plan d'execution cela :

              Index Cond: ((discriminator)::text = 'MAVALEUR'::text)

dans ma table, discriminator est declaré comme character varying(31)

dans la requete j'ai  produit.discriminator='MAVALEUR'

je suppose que si postgres cast mon champs discriminator en text s'est que la fonction d'égalité appelé par postgres prend 2 types text en parametre IN? comment est ce que je peut retrouver cette fonction qui doit etre de ce style :

equals(chaine1 text, chaine2 text)

-je suppose que le cast de charater varying vers text descend mes perfs sur la requete car du coup l'index sur le champs discriminator est utilisé 0 fois en prod car l'index contient des charater varying donc forcement il ne peut pas l'utiliser pour la comparaison?
-est ce que je dois pas plutot mettre discriminator comme champs text plutot que character varying ce qui eviterai le cast?
-si oui alors quel est l'utilité de character varying si on prevoie de faire des operations dessus car il risque de toujours caster la colonne en text?

merci pour vos reponses

#17 Re : Optimisation » Optimisation requete SQL » 28/03/2012 11:23:40

finalement la questions sur la difference entre distinct et group by resoud une partie de mon problème car l'un des deux influ sur les fonctions d'agregat, d'ou mon count(*) over qui me retourne 36 au lieu de 15 smile

bon je vais voir comment corriger la jointure qui me retourne mes doublons, ce sera plus sage smile

merci pour l'aide quand meme wink

#18 Re : Optimisation » Optimisation requete SQL » 28/03/2012 10:53:57

en fait dans l'application que j'utilise on jouait 3 requetes pour afficher un tableau de produit :


-une pour les données
-une pour la pagination(car on utilise un limit offset sur celle qui remonte les données donc je ne peut pas faire de listeproduit.size() pour connaitre le nombre de ligne...)
-une pour recupérer une valorisation

j'ai deja reussi a virer celle conernant la pagination en ajoutant count(produit0_.id) over()

j'aimerais maintenant rajouter une colonne qui effectue la valorisation au meme titre que la colonne sur la pagination

mais avant cela j'ai voulu essaye de virer les group by en ajoutant simplement un distinct


avec les group by j'ai donc 15 lignes d'affiché et 15 comme valeur du count(produit0_.id) over()  donc nickel.

sans les group by j'ai 36 lignes d'affiché (a cause d'une jointure qui me double certaines données)

avec distinct je retrouve mes 15 lignes mais mon count(produit0_.id) over() contient 36 et je voulais qu il contienne 15

-soi j'arrive à trouver la condition sur ma jointure pour ne pas avoir mes lignes doublé du coup avec distinct tout fonctionnera, mais pas si simple au vu de l'application.
-soi je remet les group by et puis tanpis je laisse comme cela vu que ca fonctionne
-soi je trouve la syntaxe avec le distinct
-soi je change count(produit0_.id) over()  et dans ce cas il existe peut etre une autre methode permettant de remonté le nombre de ligne total d'une requete

d'ailleur entre distinct et group by existe t il une difference niveau perf? sinon je ne m'embete pas et je laisse le group by en attendant de resoudre le problème sur la jointure.

ma question est juste à titre informatif vu que je suis tombé sur ce problème et je voulais comprendre pourquoi.

merci

#19 Optimisation » Optimisation requete SQL » 28/03/2012 10:16:34

palex
Réponses : 3

Bonjour

je dispose d'une requete qui realise cela :

select
        count(produit0_.id) over() as col_0_0_,
        produit0_.id as col_1_0_,
        produit0_.libelleProduit as col_2_0_
from ma_table
group by col_0_0_,col_1_0_,col_2_0_

j'ai voulu enlevé les group by et mettre un distinct

pour avoir cela:

select distinct 
        count(produit0_.id) over() as col_0_0_,
        produit0_.id as col_1_0_,
        produit0_.libelleProduit as col_2_0_
from ma_table

mais col_0_0_ ne tiens pas compte du distinct et me retourne dans le premier cas le bon nombre et dans le second cas le nombre total de ligne non "groupé" donc ma pagination n'est pas bonne du coup.

j'ai essayé de mettre  count(discinct produit0_.id) over() mais la syntaxe n'est pas autorisé.

existe t il un moyen de le faire?

merci

#20 Re : Général » Pgfouine » 19/02/2012 13:11:53

Ca marche je vais essayer tout ca demain! Merci beaucoup

#21 Général » Pgfouine » 19/02/2012 01:34:39

palex
Réponses : 2

Bonjour
J analyze souvent des requetes pgfouine qui sont remontes comme etant lente, jusqu a 70 secondes pourtant elles sont executes pres de 1000 fois ou plus et la moyenne d execution est correct sauf une 20ene de fois ou les temps sont explose sur la requete. Si je reprend la requete dans pgfouine et la rejoue sur le serveur elle met 200ms ce qui reste correct vu la requete. Ce phenomene ce produit quasiment tout les jours. J aimerais donc que cette requete arrete de sortir dans pgfouine et qu elle s execute tout le temps correctement. mais j ai l impression que le temps affiche dans pgfouine n est pas significatif et que la requete a ete execute et puis peut etre bloque par une autre du coup sont temps d execution va etre long si la requete bloquante ne rend pas la main de suite. Est il possible d isoler ce genre de chose? De savoir si une requete a vraiment mis 70sec a s executer et quel requete la peut etre bloque?

merci

#22 Re : Java » Update Et insert » 13/02/2012 12:33:06

ok ca marche, je vais faire ca, merci pour le conseil.

#23 Java » Update Et insert » 13/02/2012 11:52:14

palex
Réponses : 3

bonjour à tous

j'ai besoin dans mon application d'executer une requete d'update du style :

update synchronizedelta set datemodification = ?, doSync  = ? where groupeid = ? and num = ?;

sauf que la ligne doit exister avant de faire l'update, donc dans le meilleur des mondes, je devrais faire un truc du style :

select ....
if(exist)
  update
else
  insert

du coup j'ai systématiquement 2 requetes alors que le select, finalement va me servir uniquement 1 fois par client car une fois la ligne inséré "exist" sera toujours vrai.

Donc la solution que j'aimerais mettre en place serai de faire un truc du style (syntax non fonctionnel, il s'agit juste d'une proposition pour comprendre ce que je voudrais faire)

case when (coalesce(select id from synchronizedelta  where groupeid = ? and num = ?;, 0) > 0) then update ... ELSE insert ... END;

du coup le select est toujours joué aussi mais avec cette méthode je n'ai qu un appel à la base au lieu de 2

existe t  il une syntax similaire que je pourrais adopter?

merci beaucoup.

#24 Re : Général » Update En meme temps qu'un select » 11/01/2012 17:07:35

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

#25 Re : Général » Update En meme temps qu'un select » 11/01/2012 15:30:32

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

Pied de page des forums

Propulsé par FluxBB