Y'a moyen de faire moins usine à gaz ? - SQL/NoSQL - Programmation
Marsh Posté le 09-12-2005 à 15:37:49
Les jointures en where
J'ai jamais compris pourquoi utiliser des noms de table et attribut aussi peu significatifs de ce qu'ils sont... Ca doit faire plus pro d'être pas clair
Index, clés faciliteront peut être le bourdel Surtout quand y'aura des centeines de milliers d'enregistrements
Marsh Posté le 09-12-2005 à 15:50:53
la base, je l'ai pas écrite. les jointures à la inner join, je déteste, et en plus dans mon cas, vu le bordel, je préfère utiliser une syntaxe que j'arrive à relire naturellement.
niveau index, noms de tables et de champs, je ne peux faire aucune modification : c'est la base d'un ERP, je n'ai pas le droit de toucher à quoique ce soit.
et il y a déjà des centaines de milliers de lignes.
niveau perfs, y'a aucun souci, la requête aussi bordelique soit-elle, ne met que 2 secondes à tourner. c'est juste que c'est un méga bordel à relire, et je voulais savoir s'il y avait moyen de débordeliser tout ça. (notamment faire une jointure sur deux COUNT(*), je trouve ça très moyen)
Marsh Posté le 09-12-2005 à 16:00:58
ps: quant aux noms des tables et des champs, je vois pas ce qu'ils ont d'obscure
pro = produits
fam = familles (de produits, de tiers, de contracts, etc.)
dsk = stock par dépôts
codsoc = code société (l'erp permet à plusieurs sociétés d'utiliser la même base, c'est le cas ici d'ailleurs, et c'est pour ça que je suis dans la société 2)
codblocage = code blocage (ou phase de vie) : statut du produit, qui permet de définir s'il est permis à la vente, à l'achat ou autres règles (dynamique)
codzn3 = le plus obscure de tous : "code zone paramétrée 3", c'est à dire un champ générique que chaque société peut utiliser pour faire sa tambouille et lui appliquer ses propres règles de gestion. ici, c'est la destination du meuble.
fampro / sfapro / ssfpro = famille/sous-famille/sous-sous-famille du produit
codefam/codesfa/codessf = famille/sous-famille/sous-sous-famille (clé de la table fam, qui ne contient pas que des familles de produits, d'où le nom différent. j'ai d'ailleurs oublié d'ajouter "fam1.typtie = 'PRO'" et "fam2.typtie = 'PRO'" parceque ce sont des familles de produit et pas d'autre chose...
sigfou = sigle du fournisseur
libfam = libellé de la famille
enfin... je trouve pas que ce soit très obscure, d'autant plus que c'est un minimum normalisé (pas toujours mais bon)
Marsh Posté le 09-12-2005 à 16:04:39
ah, et pour c01 et c03 de la table DSK, à nouveau, ils ne peuvent en aucun cas être explicites... puisque c'est le paramètrage de l'outil qui leur donne un sens...
ici, c01 = stock physique au dépôt
et c03 = stock réservé pour les commandes en cours
Marsh Posté le 09-12-2005 à 16:11:40
Tu pourrais faire intervenir les conditions sur totalItems.codsoc [=2], dispoItems.ssfpro [not in (' ', 'SANS')] et totalItems.codzn3 [= 'SAL'] plus en amont (dans les requêtes avec GROUP BY), histoire de limiter les données à ce niveau.
Tu pourrais également réécrire les 2 requêtes avec GROUP BY histoire de transformer ça en :
(requête group by)
HAVING COUNT(*) = (SELECT COUNT(*) ... autre group by)
Mais ce ne sera pas plus lisible ni plus performant à mon avis ...
Tu devrais juste gagner à mettre les conditions en amont.
En gros le résultat final ressemblerait à :
Code :
|
Marsh Posté le 09-12-2005 à 16:15:31
ca serait pas du generix ca?
tes alias dans tes requetes genre FROM FAM FAM1 tu peux aps faire plus simple deja ?
FROM FAM F1? ca raccourcirait un peu la requete et ca serait peut etre plus lisible
Marsh Posté le 09-12-2005 à 16:16:50
genre, j'ai une table "osk" (oppérations sur stock) qui contient les champs :
codosk (nom de la fonction appelée, par exemple GBLV qui correspond à la validation d'un bordereau de livraison - c'est paramètré dans une autre table, m'enfin je vais pas t'expliquer tout l'ERP dans un topic), un libellé décrivant l'oppération, puis :
OPEC01, OPEC02, ... OPEC16 qui contienent soit "+", "-" ou " " (ou d'autres symboles qui définissent une action définie dans une table gérant les fonctions spécifiques des stocks), qui indique quels compteurs doivent s'incrémenter, ou se décrémenter, suivi de PRVC01, ... PRVC16 qui décrit à son tour quels stocks prévisionnels seront mis à jour. (genre, si je passe une CDE, alors mon stock immédiat "réservé" s'incrémente, tandis qu'un stock prévisionel à échéance de la facture va le décrémenter ainsi que le stock physique). on autre aussi des conditions genre "c00 <= PREP" (c00 est le compteur de mon évèment - ma commande - et PREP est un compteur virtuel (défini avec une formule dans une autre table) qui correspond ici aux préparations (les trucs prêts à mettre dans le camion). si la condition dynamique n'est pas vérifiée, alors l'action demandée ne peux pas se dérouler (genre, là dans le cadre d'une livraison, je ne vais pas valider un bon de livraison si je n'ai passur le quai le bon nombre de colis !).
on peut ensuite avec le nom d'une autre fonction à lancer, ainsi quune autre société, (afin par exemple, si je fais un mouvement de stock entre deux dépôts, quand ça décrémente l'un, puis que ça incrémente l'autre)
bref, je te passe les autres tables de paramètrage (un peu compliqué et long à expliquer)
m'enfin tu comprendras peut-être mieu pourquoi je n'ai pas des champs explicites, puisqu'ils ne le sont pas ! c'est un peu comme dans un langage de programmation, les types ne t'indiquent pas s'ils vont contenir des poules ou des carrottes, c'est à toi de décider.
Marsh Posté le 09-12-2005 à 16:21:23
Beegee a écrit : Tu pourrais faire intervenir les conditions sur totalItems.codsoc [=2], dispoItems.ssfpro [not in (' ', 'SANS')] et totalItems.codzn3 [= 'SAL'] plus en amont (dans les requêtes avec GROUP BY), histoire de limiter les données à ce niveau. |
J'y ai pensé. Seulement, "codsoc" et "codzn3" sont des variables que je passe à la requête. pour cette raison, je préfère autant se faire se peut les mettre ces variables une seule fois.
Beegee a écrit : |
Je ne suis pas sûr que mettre un HAVING et lancer une sous-requête ensuite soit un plus. En effet, le having est traîté sur le lot de résultat (toute la requête est éxécuter, puis le HAVING, sur le lot de résultat. J'ai donc peut que le SELECT qui se trouve après le HAVING soit exécuté pour chaque ligne !
Beegee a écrit :
|
hmmmm... je vais comparer quand même, mais je nesuis pas convaincu
Marsh Posté le 09-12-2005 à 16:24:11
hmmmmm, l'est pas convainquante ta requête : 0 lignes retournées
Marsh Posté le 09-12-2005 à 16:28:15
bah j'ai pas de quoi tester, hein ! à toi de le faire et de débugguer
Mais je pense que tu as compris l'esprit ... le HAVING n'apportera rien a priori, au mieux le plan d'exécution sera le même qu'avec les 2 GROUP BY.
Par contre, remonter en amont les conditions discriminantes est intéressant pour les perfs, ça permet de ne pas faire les GROUP BY sur toutes les données, mais seulement sur celles qui nous intéresse.
Marsh Posté le 09-12-2005 à 16:51:16
ça, pour les conditions en amont, je suis totalement d'accord.
mais le souci, c'est que les deux sous-requêtes pourraient bien à terme devenir des vues, hors, les vues, il ne faut pas qu'elle fassent ces filtres en dur, puisqu'il sont dynamiques. c'est dans cette optique que je les ai déporté à la fin.
Marsh Posté le 09-12-2005 à 18:54:20
C'est sous Oracle ?
Tu pourrais utiliser des vues matérialisées, mais seulement si tu as besoin de perfs supplémentaires
Marsh Posté le 09-12-2005 à 20:01:05
Nan, niveau perfs, j'ai pas de problème, c'est suffisament rapide. Nan, c'est juste que je voulais débordeliser la requête qui n'est vraiment pas belle. M'enfin c'est pas grave, le principal, c'est que ça marche
Marsh Posté le 09-12-2005 à 20:03:42
à mon avis y a pas moyen de faire mieux, comparer les 2 COUNT c'est ce qu'il y a de plus simple et de plus logique
Marsh Posté le 10-12-2005 à 03:15:20
Arjuna a écrit : ps: quant aux noms des tables et des champs, je vois pas ce qu'ils ont d'obscure |
C'est pas le sujet mais je réponds. Bah voilà justement un chat c'est pas un cht, un cochon pas un chn
Mais bon t'y peux rien, mais c'est cette tendance à vouloir raccourcir de l'info hérité des années 80 où le stockage coutait qui me fait rire. Maintenant on veut donner du sens mais on est pas fautu d'appeler l'attribut chat, "chat"
Marsh Posté le 10-12-2005 à 09:56:06
Si tu veux gagner en lisibilité, perso je trouve les "Select" dans les "From" pas très lisible.
Marsh Posté le 10-12-2005 à 11:42:53
leflos5 > ça je suis d'accord. Encore que "NombreTotalDeMeublesDisponiblesDansLaCollectionQuiVaDansLaPieceDemandee" je trouve ça un peu long comme attribut. Ecrire un nom court, ça ne sert pas seulement à gagner de la place (et je suis d'accord, ça ne sert plus à grand chose aujourd'hui), mais ça sert surtout à avoir des noms plus rapides à écrire, retenir, et ainsi éviter les fautes de frappe.
Le plus important pour moi, c'est pas vraiment le fait que ce soit abrégé ou non, ou alors dans une langue ou une autre. C'est surtout le fait que ce soit normalisé. Une fois que l'on connait la normalisation, on n'a plus besoin de connaître chaque élément, on peut deviner son sens aisément. Utiliser des noms longs sans suivre de normalisation pour les écrire empêche ceci (parceque le vocabulaire est un peu trop riche).
Autre gros avantage de l'abbréviation : ici, mise à part les tables comptables qui sont sur 5 cractères, toutes les tables sont sur 3 caractères. Ainsi, au premier coup d'oeil, on sait si une table comptable entre en jeu dans une requête ou non.
Pour les champs, mise à part quelques exceptions (z'ont pas été foutu de suivre leurs règles de nommage jusqu'au bout ) tous les champs font 6 caractères.
Ainsi, l'indentation est toujours parfaite, et ça, je trouve ça bien plus lisible dans une longue requête que des noms à rallonge chargés de sens, mais complètement en bordel parcequ'il n'y en a pas deux qui font la même taille.
gargantua307 > euh... c'est un peu l'origine de mon post. le débordelisage passer généralement par l'évitage des sous-requêtes... moi j'attends une solution pour pas les faire.
Marsh Posté le 11-12-2005 à 01:39:53
J'avais pas vu l'indentation Enfin si la norme qui donne du sens à des trucs pas toujours clair au premier coup d'oeil est même pas respectée
Et d'accord pour les nom à rallonge mais ça normalement c'est évité par une modélisation correcte
Enfin on fait pas avancer ton truc
Marsh Posté le 14-12-2005 à 16:57:49
gargantua307 a écrit : Si tu veux gagner en lisibilité, perso je trouve les "Select" dans les "From" pas très lisible. |
J'aimerais bien connaitre une solution plus lisible ........
Marsh Posté le 14-12-2005 à 17:02:57
Je la trouve très bien la requete d'Arjuna, par contre l'architecte de la base il s'est surement suicidé....
Marsh Posté le 15-12-2005 à 05:50:56
belldandys a écrit : Je la trouve très bien la requete d'Arjuna, par contre l'architecte de la base il s'est surement suicidé.... |
Marsh Posté le 15-12-2005 à 11:44:58
utilise des left outer join ou des inner join, parce que la jointure en where c pas top
Marsh Posté le 15-12-2005 à 11:51:14
j'aime pas les jointures avec des left outer et cnie. je trouve ça plus clair sans, et c'est rarement indispensable...
Marsh Posté le 15-12-2005 à 12:12:58
Tamahome a écrit : utilise des left outer join ou des inner join, parce que la jointure en where c pas top |
Ah bon ???...
Marsh Posté le 15-12-2005 à 12:18:37
belldandys a écrit : Ah bon ???... |
objectivement, c'est vrai.
mais pour 99% des cas, les jointures dans la clause where ne posent aucun problème. et c'est même parfois l'inverse.
Marsh Posté le 15-12-2005 à 12:19:59
quand à faire de "belles" jointures alors que je les fais comme un porcs entre deux sous-requête, y'a pas moyen de moyenner, l'interpréteur d'Oracle n'est plus à ça prêt ! Donc autant faire un truc qui se relit facilement.
Marsh Posté le 15-12-2005 à 14:30:10
c'est clair que :
and dispoItems.codsoc = totalItems.codsoc
and dispoItems.codzn3 = totalItems.codzn3
and dispoItems.fampro = totalItems.fampro
and dispoItems.sfapro = totalItems.sfapro
and dispoItems.ssfpro = totalItems.ssfpro
and dispoItems.sigfou = totalItems.sigfou
and dispoItems.nbItems = totalItems.nbItems
and fam1.codsoc = totalItems.codsoc
and fam1.codefam = totalItems.fampro
and fam1.codesfa = totalItems.sfapro
and fam1.codessf = totalItems.ssfpro
and fam2.codsoc = totalItems.codsoc
and fam2.codefam = totalItems.fampro
and fam2.codesfa = totalItems.sfapro
avec des inner join ca doit causer .... niveau maintenabilité, je pense que c'est à la limite du sujet de stage ..
Marsh Posté le 15-12-2005 à 15:19:39
belldandys a écrit : Ah bon ???... |
C'est pas SQL norme proof Le where n'est plus fait pour ça
C'est donc pas élégant
Maintenant ça marche probablement aussi bien et c'est vrai que c'est souvent plus lisible
Marsh Posté le 15-12-2005 à 15:25:36
ben si, ça respecte la norme.
on n'est pas obligé d'indiquer un chemin de jointure.
je vais même te dire un truc mieu : si tu fais un jointure qui suit une clé étrangère (et qu'il n'y en a qu'une), tu peux écrire ta jointure comme ça, sur un SGBD qui suit la norme correctement :
select tartempion.but
from cacahuette natural join tartempion
where cacahuere.ouça = 'dans la lucarne'
Marsh Posté le 15-12-2005 à 15:27:51
les sgbd qui supportent pas ça (à peut près tous sauf PostGre) ne sont pas compatibles avec la norme. à partir de là, autant utiliser un truc lisible, pas à la norme, mais que tout le monde comprend (la plupart des sgbd ne connaissaient pas ce mode de jointure jusqu'à il y a peu. SQL Server 6.5 par exemple ne connaissait pas à ma connaissance la syntaxe à la sauce "join" pas plus qu'Oracle 7.x
Marsh Posté le 15-12-2005 à 15:28:06
ReplyMarsh Posté le 15-12-2005 à 15:48:29
ReplyMarsh Posté le 15-12-2005 à 15:49:31
ReplyMarsh Posté le 15-12-2005 à 15:54:08
Reply
Marsh Posté le 09-12-2005 à 12:25:09
C'est bien simple.
Sur un site, on affiche des meubles par "collection", avec une disponibilité (ici, PRO.SSFPRO).
Seulement, parfois, tous les meubles de la collection ne sont pas disponibles.
Afin de donner une alternative facilement au client, on veut que le client puisse cliquer sur la "destination" du meuble (c'est à dire la pièce pour laquelle il est conçu) (ici, PRO.CODZN3).
Lorsqu'il fait ça, on doit lui afficher les collections qui contiennent des meubles dont tous ceux qui vont dans cette destination sont en stock.
Un peu complexe à faire...
J'ai pondu ça à a va-vite. C'est étonnament rapide, mais j'aimerais savoir si vous voyez un moyen évident d'améliorer cette usine à gaz
PS: j'ai rajouté "sigfou" dans les group by, mais ça n'influe pas. En effet, tous les produits d'une collection proviennent obligatoirement du même fournisseur, ça m'évite donc d'aller faire une jointure supplémentaire pour rien.
Message édité par Arjuna le 09-12-2005 à 12:35:58