[..] Requêtes SQL

Aide et conseils concernant AutoIt et ses outils.
Règles du forum
.
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

[..] Requêtes SQL

#1

Message par Hugues »

Bonjour,

J'ouvre ce post qui risque d'être long :lol: Je vais y aller par étapes :mrgreen:

J'ai 3 tables SQL, 1 table "enregistrement", 1 table "Repair" et une dernière "Valve".

Dans chaque table se trouve une colonne "Equipement"

Je souhaite récupérer dans les tables "Enregistrement" et "Valve", les valeurs contenues dans la colonne "Equipment" et ce de manière unique pour alimenter une ComboBox.

Je sais qu'il exite des joitures de table (JOIN, ACROSS, etc...), mais je "galère"...

Si une âme charitable pouvais me guider ^^

Merci par avance.
Avatar du membre
parazitenew
Niveau 7
Niveau 7
Messages : 310
Enregistré le : sam. 10 déc. 2011 15:08
Localisation : Algerie
Status : Hors ligne

Re: [..] Requêtes SQL

#2

Message par parazitenew »

Bonsoir,

Je suppose que tu utilises SQlite, je ne sais rien de SQLite, mais je travaille avec MySQL et PHP, afin d'alimenter une combobox, j'utilise ce code:

<?php
$reponse = $bdd->query('Select*From table_vertex');

while ($donnee = $reponse->fetch())
{
?>
<option><?php echo $donnee['Vertex']; ?> </option>
<?php
}

$reponse->closeCursor();
?>


La première ligne, va exécuter la requête de la sélection, $reponse est un tableau contenant le résultat de la requête.
Ensuite, j’exécute une boucle, tant que fetch() n'est pas arrivé à la fin de la table de sélection, il affiche dans la combobox la valeur de la colonne "Vertex".

à défaut de la présence d'un autre membre pour te donner al solution, essayes d'adapter ça pour autoit et SQLite.

Pour la requête, je pense que tu devrais en faire deux, une pour la table enregistrement et l'autre pour valve, ça t'évitera des erreurs:

ça sera du genre (attention ce n'est qu'un gribouillage, pas le temps de vérifier les syntaxes autoit)

$array_enreg = (SELECT Equipement FROM Enregistrement)

Boucle for ou avec FetchData()

$variable_valeur = (Récupération de la vlaeur Enregistrement.Equipement)
GUICtrlSetData(IDcombo, $variable_valeur)

Fin Boucle


ça t'aide pas beaucoup, mais ça te permettre peut être de chercher plus sur l'aide coté SQLite
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2273
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Requêtes SQL

#3

Message par jchd »

Hugues,

Tout d'abord, pardonne-moi de n'avoir pas (encore) donné suite à ton envoi. A vrai dire et à part les monstres qui me cannibalisent (je ne parle pas de mioches), j'ai trouvé que le problème de papillonnage de l'interface était à coup sûr totalement négligeable par rapport à celui posé par le choix préalable d'une saine organisation de tes données.

Por faire pardonner mon silence sur ce premier point cosmétique, je te propose de passer en revue tes soucis actuels, qui me semblent bien plus fondamentaux.
J'ai 3 tables SQL, 1 table "enregistrement", 1 table "Repair" et une dernière "Valve".
Dans chaque table se trouve une colonne "Equipement"
Premières questions :
o) quelles sont les différentes colonnes de tes trois tables ?
o) quelle est la sémantique de ces diverses colonnes ?
o) quelles relations existe-t-il entre ces colonnes de différentes tables ?
o) pourquoi disposer de trois colonnes qui, d'après ce que je comprends, contiennent la même information "Equipement" ?

En fait, les bonnes questions de base se résument plutôt ainsi : quelles sont les différentes entités que tu dois (et devras) gérer et comment sont-elles liées ?

SQL est de prime abord surprenant en ce qu'il amène à mettre en place un schéma (au sens SQL) souvent radicalement différent de ce qu'on serait tenté de mettre en place dans un programme procédural.

Ainsi, je soupçonne qu'il te faudrait une table "Equipements" et des clés étrangères des autres tables vers celle-ci.
Une règle d'or pour élaborer un schéma qui tient la route est de normaliser "raisonnablement", c'est-à-dire ne pas dupliquer dans plusieurs tables la même information (sauf des clés étrangères ou FK = foreign keys en nangliche) et de ne faire figurer dans une table que ce qui caractérise les entrées (rangées) quelle contient.

Pour donner un aperçu de ce qu'il faut faire ou ne pas faire, prenons quelques fonctions d'un smartphone. On a un répertoire téléphonique avec numéros de portable, de domicile, de boulot, et de maison de vacances, un agenda avec rendéz-vous, des notifications d'anniversaires, des adresses mail, des notes en texte, des adresses postales, des codes de porte, que sais-je.

Un design atroce : une seule table !
Prénom
Nom
N° portable ; mélodie
N° domicile ; mélodie
N° boulot + n° de poste si pas de ligne directe ; mélodie
N° vacances ; mélodie
Adresse postale
Code interphone
Date anniversaire
Texte libre
eMail perso
eMail boulot
Date/heure rdv1 ; délai notification avant ; mélodie ; répéter jour ; répéter semaine ; répéter mois
Date/heure rdv2 ; délai notification avant ; mélodie ; répéter jour ; répéter semaine ; répéter mois
Date/heure rdv3 ; délai notification avant ; mélodie ; répéter jour ; répéter semaine ; répéter mois
Date/heure rdv4 ; délai notification avant ; mélodie ; répéter jour ; répéter semaine ; répéter mois
Date/heure rdv5 ; délai notification avant ; mélodie ; répéter jour ; répéter semaine ; répéter mois
Date/heure rdv6 ; délai notification avant ; mélodie ; répéter jour ; répéter semaine ; répéter mois
Date/heure rdv7 ; délai notification avant ; mélodie ; répéter jour ; répéter semaine ; répéter mois
...

Les colonnes sont figées par design et on se traîne toutes les colonnes pour chaque entrée. Maintenant s'il faut rechercher avec qui j'avais rendez-vous le 3 septembre à 9h45, on doit rechercher dans toutes les entrées, mais aussi dans les 7 colonnes de rendez-vous prévues. Les colonnes deviennent elles-mêmes des données et c'est à proscrire absolument.

Ce désign n'est pas du tout adapté à une base SQL. On doit analyser et raisonner par entités.

La première entité ce sont les personnes. Certains attributs leur sont attachés (nom, prénom, anniversaire, photo (icône de répertoire), n° de sécu ou autre si besoin). On leur attibue un identifiant, typiquement un entier immuable et unique, sans signification, qui est leur "étiquette" personnelle dans cette base et à laquelle on va se référer dans les autre tables. Un identifiant nurérique est non seulement très efficace, mais aussi non ambigü ; un prénom ne suffirait bien sûr pas à assurer l'unicité, mais pas plus associé avec un nom. De plus un nom (officiel) peut changer (mariage, divorce, changement de nom).

Seconde entité : les numéros de téléphone et leurs attributs (groupe, mélodie, préfixe pays, type [portable, domicile, ...], blacklistage, visio possible, ...). Idem, chaque entrée va se voir attribuer un identifiant entier unique. Mais on va aussi ajouter dans une colonne une référence à la personne (ou société, c'est un terme générique ici) en stockant aussi l'identifiant de cette personne dans la table des personnes. C'est ce qu'on appelle une clé étrangère. Une fois déclarée en tant que telle, cette clé commune va assurer l'intégrité de la base. Ainsi une même personne pourra avoir différents numéros avec différents attributs sans que ces informations n'aient à figurer dans l'entrée "Personnes" sous forme de colonnes en nombre figé. C'est depuis la table "Numéros" qu'on va "pointer" vers la personne concernée. La duplication d'information est évitée et l'intégrité assurée.

Et ainsi de suite avec les autres entités (adresses mails, rendez-vous, etc.)

Ce type de lien est peu utilisé dans un programme procédural : en général on a tendance à stocker un pointeur (ou une référence) de la table parent vers la table fille, où il faut souvent comprendre "table" par "tableau mémoire". En SQL c'est presque toujours l'inverse qu'il faut faire : stocker dans les tables dépendantes (filles) l'identifiant du parent.

Ces liens directs permettent de modéliser les liens de UN à UN, de UN à PLUSIEURS et de PLUSIEURS à UN. Une table intermédiaire ne contenant que des identifiants de deux tables permet de modéliser les relation de PLUSIEURS à PLUSIEURS.

Cette démarche amène à dissocier clairement les entités en relation et à clarifier le type de ces relations en l'inscrivant dans le schéma même de la base (la composition des différentes tables et leurs relations). Il ne faut pas avoir peur de voir se multiplier les tables, car SQL est justement conçu pour jongler aisément avec des relations complexes. Il ne faut pas oublier que les moteurs SQL sont (dans leur très grande majorité) des SGBDR (systèmes de gestion de base de données RELATIONNELLES).

C'est seulement si le maquettage démontre des goulets d'étranglement rédhibitoires qu'il faut aborder la dénormalisation et accepter de dupliquer certaines colonnes dans deux ou plusieurs tables pour satisfaire aux exigences pratiques de vélocité. Les informations ainsi dupliquées doivent alos être maintenues en cohérence par les applicatifs et non plus par les mécanismes de la base, ce qui est considérablement plus fragile : si un programme modifie l'une des données dupliquées, alors il doit effectuer la modification dans toutes les autres tables où figure cette ancienne donnée, le tout de façon transactionnelle (on fait tout ou rien du tout). A défaut, la base devient incohérente et source de problèmes insurmontables. Mais, ici comme ailleurs, le diable se cache dans l'optimisation précoce.

Alors dans tout ça, qu'est-ce qu'une jointure ?
Dans notre petit exemple, ça peut être la mise en correspondance de l'identifiant d'une personne dans la table "Personnes" et de l'identifiant "PersonneId" dans la table des numéros, par exemple, ou celle des adresses mail. Et SQL excelle à ce petit jeu, même si ça semble tordu et parfois un poil lourd à codifier. Ainsi, si l'on souhaite proposer d'envoyer un mail privé à quelqu'un en ce jour d'anniversaire, on pourra faire la requête fictive suivante :

select prénom, nom, email from emails as E join personnes as P on e.personneID = p.ID where e.type = 'P' and e.anniv = substr(date('now'), 6);

si type = 'P' dénote une adresse mail privée dans la table des adresses email.

En résumé, pour toi le vrai problème consiste déjà à dissocier les véritables entités et expliciter leurs relations. Promis, je suivrai ce sujet plus assidûment !
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Requêtes SQL

#4

Message par Hugues »

Bonjour,

Pas de soucis pour le problème précedent, j'ai suivi tes conseils et c'est à 90% résolu (si tu n'as pas regardé encore c'est pas grave ^^).

Pour revenir au SQL, je n'ai plus que 2 tables (enregistrement et valve).

En fait, je developpe un logiciel de suivi d'outillages (j'en ai deja créé un mais il est pas assez "puissant").

Dans ce nouveau, je voudrais enregistrer le matériel changé pour ensuite, d'une avoir un suivi de réparation, et de deux pouvoir faire des statistiques (quelle station est la plus consommatrice, le nombre de fois qu'un outil a été changé, etc... ) et me sortir un graphique (sorte de tableau de bord ^^) et bien sûr envoyer par EMail en optionnel (ça je sais faire ^^).

C'est pour cel que je demande conseil sur la structure de ma base, car je ne voudrais pas être bloqué au niveau des requêtes par une mauvaise structure comme tu l'as mentionné precdemment.

Ci joint ma base: BASE SQL

Merci par avance pour votre aide.
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Requêtes SQL

#5

Message par Hugues »

Bonjour,

Bon j'avance un peu...

Pour le moment, je suis toujours avec 2 tables SQL qui ont le même nombre colonnes, mais pas le même nom pour certaines ^^.

Ma problématique est que je devrais (vraisemblable) intégrer d'autres entrées dans cette base.

Faut-il que je créér:
- une table par outillage avec nom de colonnes identiques pour chaque outillage (je pencherai bien pour cette solution)? -> Cela induit au moment de l'enregistrement de controler si une table existe ou pas et la créér si elle n'existe pas..


Si quelqu'un à un exemple de structure de base pour mon sujet je suis preneur ^^.

Je sais que je suis vague mais j'ai pas beaucoup d'experience dans sql ^^
Avatar du membre
mikell
Spammer !
Spammer !
Messages : 6292
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [..] Requêtes SQL

#6

Message par mikell »

Hugues a écrit :Je sais que je suis vague
Non, c'est pire
J'ai regardé ta base du post #4. Ya des tables vides, avec des noms de colonne pas évocateurs (Valve ?? :shock: ) et pas moyen d'avoir la moindre idée de comment doit être traité le contenu de ces tables, ni à quoi ça peut bien servir
C'est certainement très clair dans ta tête mais pour moi (et pour les autres aussi j'imagine) c'est un flou artistique géant
Un exemple précis serait bienvenu indispensable ake sinon pas moyen de faire le moindre commentaire sur la structure, parlons même pas des requêtes ^^
par exemple : je veux entrer ceci dans le but d'obtenir cela - avec exemple d'application évidemment

Quand tu demandes s'il vaut mieux des roues rondes ou carrées, il est très important de préciser si c'est pour utiliser sur route ou dans des escaliers
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Requêtes SQL

#7

Message par Hugues »

Salut,

Je tourne le sujet dans tout les sens ^^, mais je pense trouver un fil directeur...

Pour exposer mon problème:

J'ai plusieurs lignes de production, chaque lignes de productions à un nombre x de stations, chaque station est équipée de matériel.
Selon le matériel, il a soit un numéro de plan, un type, un identifiant unique.

C'est pour cela que je vais gérer en fait 1 table par outillage. Cela va me permettre de faire des requêtes plus poussées et aussi de suivre mon matériel en fonction des ses évolutions.

Ainsi dans chaque Table, je stockerai: ID, Date, Ligne, Station, Matériel enlevé, Celui mis en place, son emplacement sation, commentaire, demandeur. Par la suite je ferais une table "suivi des réparation" globale dans laquelle je stockerai les interventions faites sur chaque matériel.

Attention tout n'est pas fonctionnel...

Mon projet complet ici
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2273
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Requêtes SQL

#8

Message par jchd »

Hugues,

Je reviens à la charge, en compagnie du chat potté.

Primo, tu parles d'une table par outillage, mais tu n'as pas parlé d'outillage dans la phrase qui précède. Est-ce que pour toi matériel = outillage ? Il va te falloir adopter une terminologie cohérente et fixe, sinon ça va tourner à Koh-Lanta.

Secundo, "une table par outillage" serait un non-sens absolu qui te ferait écrire des milliers de lignes de code indémerdables et non-maintenables pour rien. Un nom de schéma (par exemple de table ou de colonne) ne dois JAMAIS être une variable.

Tertio, à jeter un coup d'oeil dans tes .INI, je peux de suite te dire que TOUT ce qui y figure est à mettre dans des tables SQL. Si tu tiens à avoir une certaine flexibilité, tu auras un seul .INI avec une seule ligne : l'emplacement de ta base de données sur le disque local. Tout le reste sera dans la base, absolument tout.

Je ne regarde même pas le .AU3 qui n'a rien à faire là pour l'instant, il sert seulement à t'embrouiller et t'éloigner des vraies préoccupations du moment.

D'après le peu que je capte de ta problématique, tu as plusieurs lignes de fabrication (=> une table des lignes et encore, je ne suis pas certain que ce soit impératif), chacune est agencée en stations (=> une table des stations) et chacune est équipée de matériels de production (=> une table des matériels).

Je ré-enfourche mon cheval de campagne et t'invite à télécharger SQLite Expert Personal http://www.sqliteexpert.com/download.html. C'est absolument tout ce dont tu as besoin dans un premier temps. Cet outil va te permettre de construire une base stable et fonctionnelle ; tu n'as pas besoin de charger toutes les données et qu'elle soit exploitable en pratique.

Donc et sauf besoin impérieux d'une table des lignes, partons sur ce qui me semble le minimum pour planter le décor :

o) une table des stations nommée "Stations" (il faudra choisir entre "Cell" et "Station") qui comprendra l'Id (identifiant) de la station, son nom (d'après ce que je pige, ça peut être ABS9_1_02, ABS9_2_16, HASx_1_110, ... [ce sont les sections de Material.ini]) et la ligne à laquelle elle appartient. D'ailleurs, je soupçonne que tes lignes sont ABS9_1, ABS9_2 et HASx_1 et que ce qui suit ans le nom de la station est son numéro.
Question immédiate : existe-t-il des stations qui sont ou seront un jour communes à plusieurs lignes ? Si oui, table des lignes impératives, sinon on peut éventuellement s'en passer.

o) une table des matériels nommée "Matériels" (perso je pense que "Equipement" serait plus parlant, mais je peux me tromper) où l'on trouvera son Id, sa description, sa référence, son fournisseur, son n° de série le cas échéant, date (je veux bien, mais date de quoi, faut être précis ?) alors disons date d'entrée dans le stock du parc.

Maintenant, une chose que tu occultes : quand tu décris qu'il y a un robot TX60 sur telle station et que tu énumères les cartes qui composent de robot, tu es en train de manipuler une nouvelle entité : les composants de tel ou tel matériel (ici encore équipement sonne plus juste). Tu mets "Carte robot TX60=Carte RPS;Carte ARPS;Carte RSI2;Carte Starc;Carte Profibus;CPU" mais en fait tu ne peux pas mettre un tableau (les différentes cartes électroniques du robot) dans une seule colonne d'une table.
De la même manière, tu écris : "Outil d'emmanchement=RT01272050110;RT01272050111;RT01272050112;RT01272050113;RT01272050114" mais en fait tu indiques là que sur cette station il y a 5 outils d'emmanchement, ce qui veut dire 5 rangées dans la table "Matériels" (ou "Equipement").

Il te faut donc soit stocker que la station X comporte telle série de composants, soit gérer une table "Composants" en lien avec la table "Equipement" (je préfère définitivement ce terme-là). Les deux possibilités ont des avantages et des inconvénients. Dans le premier cas, rien n'empêcherait d'affecter une carte ProfiBus de TX60 à une station qui n'utilise pas de robot ; dans le second cas on a un niveau de complexité supplémentaire à gérer. Le choix dépend du contexte pratique, en regardant au-dessus des nuages (en pensant à l'avenir et aux évolutions potentielles).

De la même façon, tu peux ou pourrais avoir à gérer le n° de série de cartes, par exemple. Suppose qu'une carte ARPS tombe en rade. Tu la changes et la renvoies au fournisseur sous garantie, puis celui-ci la répare et te la renvoie. Un beau jour tu es amené à monter cette carte sur un autre robot et pof, elle retombe en rade au bout de 3 jours. Le truc recommence plusieurs fois. Si tu ne gères pas son n° de série, tu n'y verras que du feu, mais si tu le gères, tu pourras t'apercevoir que cette carte retombe en rideau à chaque fois et que c'est elle qui a forcé l'arrêt de production 5 fois en 8 mois.
Il peut ou pourra aussi exister des versions différentes de certains composants ou équipements avec potentiellement des incompatibilités de versions ; je n'en sais rien, je ne connais rien à ton métier.

Autre cas de figure : le fournisseur rappelle les cartes Prokist TS2000 ayant un n° de série entre XXX et YYY. Comment vas tu faire pour savoir où aller les récupérer ? Arrêter la prod pour démonter les bestioles et vérifier chaque station équipée me semble sous-optimal.

Pour ce qui est des interventions, attends d'avoir déjà correctement mis en place les outils pour décrire ton parc installé.

Tout ces "détails" impactent directement l'architecture de la base, son schéma, que tu vas devoir mettre en oeuvre.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Requêtes SQL

#9

Message par Hugues »

Merci Mikell & jchd pour vos réponses.

Je relis vos posts de manière posée :mrgreen:
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2273
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Requêtes SQL

#10

Message par jchd »

Lis tes MPs aussi.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
mikell
Spammer !
Spammer !
Messages : 6292
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [..] Requêtes SQL

#11

Message par mikell »

@jc
Ya pas à dire, un commentaire de pro, c'est le must :mrgreen:

@Hugues
Personnellement, avant même de penser à des tables, j'aurais essayé de me définir une "arborescence" aussi précise et complète que possible de toutes les données à archiver, surtout sans oublier le moindre petit "détail" évoqué par jc
Ensuite j'aurais essayé de définir précisément les futures requêtes possibles, avec leurs différents "chemins", sachant que c'est sur les "détails" que s'effectueront 99% des requêtes
Tout ça avec l'espoir fou que cette vision d'ensemble permette de mettre en évidence une structure optimale Image
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2273
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Requêtes SQL

#12

Message par jchd »

Désolé de vous imposer des murs de texte, mais j'essaye de mettre en évidence des points clés qui, si on les néglige, risquent de rendre l'ensemble ingérable ou à reconstruire entièrement.

De mon point de vue, la problématique est extrêmement similaire à la gestion d'un parc informatique d'une boîte et des interventions de maintenance et d'évolution associées, la gestion des logiciels installés en moins. Donc rien d'exceptionnel, mais c'est effectivement dans les spécificités que le diable nous attend de pied ferme.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
mikell
Spammer !
Spammer !
Messages : 6292
Enregistré le : dim. 29 mai 2011 17:32
Localisation : Deep Cévennes
Status : Hors ligne

Re: [..] Requêtes SQL

#13

Message par mikell »

Désolé de vous imposer des murs de texte
Tu déconnes ?! ils sont SUPER tes commentaires. C'est quasiment niveau tutorial Image
" L'échec est le fondement de la réussite. " (Lao-Tseu )
" Plus ça rate, plus on a de chances que ça marche " (les Shadoks )
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Requêtes SQL

#14

Message par Hugues »

Je suis d'avis avec Mikell. Des commentaires précis qui permettent de mettre en avant tel avantage ou inconvénient de nos choix.
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Requêtes SQL

#15

Message par Hugues »

jchd a écrit : Je ré-enfourche mon cheval de campagne et t'invite à télécharger SQLite Expert Personal
C'est fait ^^
jchd a écrit : o) une table des stations nommée "Stations" (il faudra choisir entre "Cell" et "Station") qui comprendra l'Id (identifiant) de la station, son nom (d'après ce que je pige, ça peut être ABS9_1_02, ABS9_2_16, HASx_1_110, ... [ce sont les sections de Material.ini]) et la ligne à laquelle elle appartient. D'ailleurs, je soupçonne que tes lignes sont ABS9_1, ABS9_2 et HASx_1 et que ce qui suit ans le nom de la station est son numéro.
Oui, exemple -> ABS9_1_32 -> Ligne de production ABS9 ligne 1 (ABS9_1), station 32 (32) ^^
jchd a écrit : Question immédiate : existe-t-il des stations qui sont ou seront un jour communes à plusieurs lignes ? Si oui, table des lignes impératives, sinon on peut éventuellement s'en passer.
Oui les stations peuvent être communes à plusieurs lignes , j'ai des stations qui porte le même nom sur des lignes différentes mais qui ont des équipement différents... donc tables des lignes impératives effectivement.
jchd a écrit : o) une table des matériels nommée "Matériels" (perso je pense que "Equipement" serait plus parlant, mais je peux me tromper) où l'on trouvera son Id, sa description, sa référence, son fournisseur, son n° de série le cas échéant, date (je veux bien, mais date de quoi, faut être précis ?) alors disons date d'entrée dans le stock du parc.
La date correspondait à la date de son démontage (inutile maintenant si je créé une table pour le suivi des réparations).
jchd a écrit : Maintenant, une chose que tu occultes : quand tu décris qu'il y a un robot TX60 sur telle station et que tu énumères les cartes qui composent de robot, tu es en train de manipuler une nouvelle entité : les composants de tel ou tel matériel (ici encore équipement sonne plus juste). Tu mets "Carte robot TX60=Carte RPS;Carte ARPS;Carte RSI2;Carte Starc;Carte Profibus;CPU" mais en fait tu ne peux pas mettre un tableau (les différentes cartes électroniques du robot) dans une seule colonne d'une table.
De la même manière, tu écris : "Outil d'emmanchement=RT01272050110;RT01272050111;RT01272050112;RT01272050113;RT01272050114" mais en fait tu indiques là que sur cette station il y a 5 outils d'emmanchement, ce qui veut dire 5 rangées dans la table "Matériels" (ou "Equipement").

Il te faut donc soit stocker que la station X comporte telle série de composants, soit gérer une table "Composants" en lien avec la table "Equipement" (je préfère définitivement ce terme-là). Les deux possibilités ont des avantages et des inconvénients. Dans le premier cas, rien n'empêcherait d'affecter une carte ProfiBus de TX60 à une station qui n'utilise pas de robot ; dans le second cas on a un niveau de complexité supplémentaire à gérer. Le choix dépend du contexte pratique, en regardant au-dessus des nuages (en pensant à l'avenir et aux évolutions potentielles).

De la même façon, tu peux ou pourrais avoir à gérer le n° de série de cartes, par exemple. Suppose qu'une carte ARPS tombe en rade. Tu la changes et la renvoies au fournisseur sous garantie, puis celui-ci la répare et te la renvoie. Un beau jour tu es amené à monter cette carte sur un autre robot et pof, elle retombe en rade au bout de 3 jours. Le truc recommence plusieurs fois. Si tu ne gères pas son n° de série, tu n'y verras que du feu, mais si tu le gères, tu pourras t'apercevoir que cette carte retombe en rideau à chaque fois et que c'est elle qui a forcé l'arrêt de production 5 fois en 8 mois.
Il peut ou pourra aussi exister des versions différentes de certains composants ou équipements avec potentiellement des incompatibilités de versions ; je n'en sais rien, je ne connais rien à ton métier.

Autre cas de figure : le fournisseur rappelle les cartes Prokist TS2000 ayant un n° de série entre XXX et YYY. Comment vas tu faire pour savoir où aller les récupérer ? Arrêter la prod pour démonter les bestioles et vérifier chaque station équipée me semble sous-optimal.
Dans l'idéal ce que tu expliques ici serait un must ^^, pour le coup un vrai logiciel de GMAO.

Après je n'ai pas besoin d'avoir un suivi tellement précis.

A mon niveau, dans la description de l'équipement le plus important est son "SON NOM", "SA DESCRIPTION", "SA VERSION", et en optionnel une "SA PHOTO", exemple: "Outil de sertissage", "RT01272050562", "Version 1", "toto.bmp".
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2273
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Requêtes SQL

#16

Message par jchd »

Bon, je commence à voir à peu près ce qu'il te faut. Je vais essayer de débloquer un peu de temps pour te faire une maquette.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2273
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Requêtes SQL

#17

Message par jchd »

Hugues,

Désolé d'avoir été aussi lent, mais le temps me manque.

Pour commencer avec un embryon de maquette, j'ai concocté ce qui suit. Bien des choses sortent
purement de mon chapeau, mais ça pose un socle sur lequel cogiter pour élaborer une structure
qui tienne la route, aujourd'hui et demain.

A) Les tables

a) une table des lignes
b) une table des stations
c) une table des postes
d) une table des fournisseurs
e) une table de description des équipements (qu'ils soient disponibles ou pas)
f) une table du parc des équipements physiquement disponibles
g) une table de demandeurs
h) une table de maintenance
i) une table hors données applicatives pour la configuration et intendance interne
j) une table des anomalies relevées par le soft

B) Un peu plus en détail

NOTE : j'ai fait des copier/coller décalés dans le temps, donc il pourrait exister des
différences entre le SQL qui figure ici et la base jointe, qui seule fait autorité.

a) Rien de spécial
CREATE TABLE "Lignes" (
"LigneId" INTEGER NOT NULL PRIMARY KEY,
"LigneNom" CHAR NOT NULL);

b) RAS non plus, sauf une chose : comprendre station au sens station de métro !
L'analogie étant qu'une station de métro a parfois des correspondances sur plusieurs lignes.
Si on convient d'un rdv, il faut préciser la station ET la ligne (et le quai pour le métro).
Plus bas, le regroupement de ces deux informations est appellé un poste.
CREATE TABLE "Stations" (
"StationId" INTEGER NOT NULL PRIMARY KEY,
"StationNom" CHAR NOT NULL);
J'ai ajouté à ça une colonne temporaire StationNom5 avec des noms de stations compatibles avec un tri.

c) Petite subtilité donc : on lie un poste à la station et à la ligne. Par la suite on verra qu'on
peut ainsi différencier les postes selon leur ligne car il n'est pas évident qu'une station
commune à plusieurs lignes utilise tout son équipement pour chaque ligne à laquelle elle appartient.
Cette notion de poste est donc plus précise et plus facile à manipuler que le couple {ligne, station}.
Chaque poste est simplement décrit par son Id propre et les clés étrangères vers sa ligne et sa station.
CREATE TABLE "Postes" (
"PosteId" INTEGER NOT NULL PRIMARY KEY,
"LigneId" INTEGER NOT NULL CONSTRAINT "fkPostesLigne" REFERENCES "Lignes"("LigneId") ON DELETE RESTRICT ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
"StationId" INTEGER NOT NULL CONSTRAINT "fkPostesStation" REFERENCES "Stations"("StationId") ON DELETE RESTRICT ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED);

d) RAS de spécial, on va y mettre ce qu'il faudra (nom, adresse, contacts technique, SAV et commercial, ...)
CREATE TABLE "Fournisseurs" (
"FournId" INTEGER NOT NULL PRIMARY KEY,
"FournNom" CHAR NOT NULL);

e) Ah, les équipements ! Ici on stocke leur définition mais pas leur identité matérielle.
Outre un Id, une référence fournisseur, une description, une Id fournisseur, la version, je mets
une colonne Classe qui peut contenir A S ou M pour indiquer si l'équipement est Automatique (robot)
Semi-automatique (machine à sertir) ou Manuel (marteau). Je n'ai aucune idée de l'intérêt en pratique
pour ton contexte mais c'est une notion qui peut peut-être s'avérer utile ou servir de modèle à une
toute autre idée. C'est plus pour montrer comment ça peut marcher avec une contrainte d'entrée.
Si ça a un sens, je pense qu'il faudrait ajouter une classe O pour outillage, mais bon.
une Id de l'équipement parent : c'est l'Id du bras pour un outillage de bras et l'Id du robot pour un
bras et c'est NULL pour un tournevis comme pour un robot. Avec cette colonne on peut donc indiquer
ainsi que l'objet ne peut avoir d'existence sur un poste que comme partie d'un ensemble plus vaste.
Par contre ce mécanisme ne permet pas tel quel de lister par exemple tout ce que doit comporter un
robot de soudure par points, par exemple. On verra ce qui s'avère nécessaire.
On peut loger un chemin complet sur une photo (il n'est pas judicieux de placer des paquets d'images
dans la base, un sous-répertoire sera bien plus adequat).
CREATE TABLE "Equipements" (
"EquipId" INTEGER NOT NULL PRIMARY KEY,
"Reference" CHAR NOT NULL,
"Description" CHAR COLLATE NOCASE DEFAULT '',
"FournId" INTEGER CONSTRAINT "fkEquipementFournisseur" REFERENCES "Fournisseurs"("FournId") ON DELETE RESTRICT ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
"Version" CHAR DEFAULT '',
"Classe" CHAR NOT NULL DEFAULT 'A',
"ParentId" INTEGER CONSTRAINT "fkEquipParent" REFERENCES "Equipements"("EquipId") ON DELETE RESTRICT ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
"Photo" CHAR NOT NULL DEFAULT '',
CONSTRAINT "ckEquipClasse" CHECK(EquipClasse in ('A', 'S', 'M')));

f) Notre parc physique. On y trouve normalement tout ce qui est soit installé sur un poste soit
en stock (posteId à 0). Chaque équipement est assigné à un poste ou au stock, avec son
numéro de série le cas échéant. On peut par exemple convenir que le matos hors d'usage soit assigné
à un poste fictif lié à une ligne et une station fictives 'Atelier de réparation'. On peut en
créer plusieurs selon qu'on prévoit une réparation sur place dans un atelier d'électricité, de tests,
de mécanique, d'entretien, ... ou un retour chez le fournisseur. C'est ce que j'ai finalement créé,
quitte à scratcher si ça n'a vraiment pas de sens potentiel.
CREATE TABLE "Parc" (
"ParcId" INTEGER NOT NULL PRIMARY KEY,
"ParcEquipId" INTEGER NOT NULL CONSTRAINT "fpParcEquip" REFERENCES "Equipements"("EquipId") ON DELETE CASCADE ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
"ParcSerial" CHAR NOT NULL DEFAULT '',
"ParcPosteId" INTEGER CONSTRAINT "fkParcPoste" REFERENCES "Postes"("PosteId") ON DELETE SET NULL ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED);

g) Qui demande d'intervenir ? C'est ici que ça se passe.
Table des personnes/services habilités à requérir une intervention. J'ai mis des colonnes au pif.
CREATE TABLE "Demandeurs" (
"DemandeurId" INTEGER NOT NULL PRIMARY KEY,
"DemandeurNom" CHAR NOT NULL DEFAULT '',
"DemandeurService" CHAR NOT NULL DEFAULT '',
"DemandeurFonction" CHAR NOT NULL DEFAULT '');

h) La maintenance de tout ça.
Outre le sempiternel Id, une date d'intervention, la référence à un poste, celle à un demandeur (par Id
car pas question de mettre des noms ici et ça permet d'éviter que le personnel de ménage ne soit à
l'origine d'un remplacement de robot).
J'ai pifométré la possibilité d'enregistrer l'heure de début et de fin d'intervention, ainsi bien sûr
que les Ids de l'équipement déposé (ou Null pour une nouvelle installation) et de celui qui a pris sa
place (ou NULL si dépose seule). Un mémo de commentaire complète la table.
On peut aussi y stocker la planification des interventions à réaliser, éventuellement avec une colonne en
indiquant l'urgence ou autre détail.
CREATE TABLE "Maintenance" (
"MaintId" INTEGER NOT NULL PRIMARY KEY,
"Date" CHAR NOT NULL DEFAULT (date('now')),
"PosteId" INTEGER NOT NULL CONSTRAINT "fkMaintPoste" REFERENCES "Postes"("PosteId") ON DELETE RESTRICT ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
"DemandeurId" INTEGER NOT NULL CONSTRAINT "fkMaintDemandeur" REFERENCES "Demandeurs"("DemandeurId") ON DELETE RESTRICT ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
"HeureDebut" CHAR DEFAULT (time('now')),
"ParcIdOut" INTEGER NOT NULL CONSTRAINT "fkMaintParcOut" REFERENCES "Parc"("ParcId") ON DELETE RESTRICT ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
"ParcIdIn" INTEGER NOT NULL CONSTRAINT "fkMaintParcIn" REFERENCES "Parc"("ParcId") ON DELETE RESTRICT ON UPDATE CASCADE DEFERRABLE INITIALLY DEFERRED,
"HeureFin" CHAR DEFAULT (time('now')),
"Comment" MEMO DEFAULT '');

i) On va stocker ici tout un tas de paramètres utiles un peu comme dans un fichier .INI
L'appli n'a plus qu'à savoir où aller chercher la base et tout est dedans. Une seule valeur
dans un fichier .INI du nom de l'appli permet de passer d'une base de test à une base réelle.
CREATE TABLE "_Registre" (
"Id" INTEGER NOT NULL PRIMARY KEY,
"Clef" CHAR NOT NULL,
"Valeur" CHAR NOT NULL);

j) Il n'est pas inutile de prévoir cette table qui permet au soft de noter dans un coin des choses
bizarres sans qu'elles ne soient des erreurs bloquantes. Une boîte de dialogue peut rappeler de
temps à autre (e.g. au lancement du soft) que certains points sont à traiter.
CREATE TABLE "_Anomalies" (
"Id" INTEGER NOT NULL PRIMARY KEY,
"Date" CHAR NOT NULL DEFAULT (Datetime('now')),
"Anomalie" CHAR NOT NULL DEFAULT '',
"Résolue" BOOLEAN NOT NULL DEFAULT 0);

Si on veut gérer les choses de façon un peu carrée, on devrait gérer des demandes dans une table séparée
car une demande devrait pouvoir porter sur plusieurs choses, par exemple la remise à niveau de plusieurs
postes avec un nouveau jeu d'équipements, à réaliser sur une quinzaine de jours.

J'ai créé quelques entrées pour qu'on puisse jouer avec le tout.


Il y a aussi quelques vues. Une vue SQL est en fait un SELECT prédéfini qu'on peut consulter ou utiliser
dans une requête plus complexe comme si c'était une table.

Vue des postes par ligne et station. On s'aperçoit que le fait d'avoir un "nom" de station numérique (et si
je comprends bien des sous-stations mais je m'en suis aperçu plus tard, avec les stations 56 que je croyais
commentées) ne permet pas une vue hiérarchique idéale. On peut corriger ça, ce n'est pas grave. J'ai mis
une "béquille" pour contourner l'obstable avec la colonne StationNom5, mais c'est temporaire et non important.
CREATE VIEW "LesPostes" AS
select posteid ID,
case when posteid > 0
then lignenom || '_' || stationnom
else stationnom
end Poste
from postes natural join lignes natural join stations
order by ligneid, stationnom5;

Vues des équipements connus, par fournisseur, référence et appartenance à un sur-ensemble. J'ai volontairement
introduit le contrôleur de robot Stäubli CS8C pour montrer que l'appartenance peut être un graphe (orienté et
acyclique), visible dans la colonne résultat "Associé à".
CREATE VIEW "LesEquipements" AS
select equipid ID,
nom Fournisseur,
Référence,
description Description,
case when parentid isnull
then ''
else (select référence from equipements E where E.equipid = EQ.parentid)
end "Associé à"
from fournisseurs join equipements EQ using (fournid)
order by nom, référence, parentid;

Vue du parc physique. On y trouve le poste où se trouve l'équipement, les informations sur
cet équipement précis avec son n° de série. J'ai créé des exemples d'équipements hors lignes
réelles, supposé se trouver dans certains ateliers pour remise en état ou retour fournisseur.
Ce n'est qu'un exemple de ce qu'on peut mettre en place.
CREATE VIEW "LeParc" AS
select posteid,
case when parcposteid > 0
then lignenom || '_' || stationnom
else stationnom
end Poste,
equipid,
description,
référence,
parcserial "N° de série"
from parc
left join postes on parcposteid = posteid
natural join lignes
natural join stations
join equipements E on E.equipid = parcequipid
order by Poste;

C'est en consultant les vues qu'on peut mieux se rendre compte de ce qu'on peut obtenir.

Je vais m'arrêter là pour ce ... soir ou matin, je ne sais plus trop !

Suivront rapidement des exemples de requêtes jouables sur la base de démo, même si les données sont bidon.
Mais je ne sais pas trop quelle requêtes seraient parlantes/utiles pour toi. Tu me diras.

Une fois ce squelette un peu dégrossi et quand la poussière sera retombée, on va mettre en ligne la
maintenance avec quelques exemples d'utilisation. Il y a encore beaucoup de finesses à régler, comme les
requêtes en texte désaccentué, les triggers (déclencheurs) et plus technique, les clauses d'action sur
modification ou suppression de clé étrangères [pour l'instant presque tout est à ON DELETE RESTRICT]. Ce
point peut sembler obscur mais il va s'éclairer par la suite et conditionne des aspects en réalité
fondamentaux du fonctionnement de l'ensemble. On y reviendra.

L'habillage de tout ça (joli GUI et tout) est bien ultérieur et à envisager seulement quand la base sera
stable et utilisable "à la main" via SQLite Expert. Note, la version payante de Expert permet l'utilisation
de scripts LUA ou Pascal qui peuvent parfaitement se substituer à un habillage AutoIt au niveau fonctionnel
mais certes pas au niveau cosmétique (ce dont je me fous éperdument, à dire vrai).
Hugues.zip
Base exemple
(6.83 Kio) Téléchargé 119 fois
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Requêtes SQL

#18

Message par Hugues »

Salut,

Pas de soucis, le projet n'est pas urgentissime et j'ai la chance que tu ai pu te pencher sur mon problème.

Tu m'as fournis une base déjà très fournie, élaborée, de très bonne qualité, et ce avec des vues sql que je ne connaissais pas.

Je suis entrain d'étudier tout cela, de ma part j'avais commencé quelque chose (des choses sont ressembalantes mais loin d'être aussi abouties).

Je vais voir si je peux mettre 2 ou 3 variantes à ta source pour faire en sorte que cela corresponde à mes besoins.

Je te remercie et je reviens ici très vite ^^
Avatar du membre
jchd
AutoIt MVPs (MVP)
AutoIt MVPs (MVP)
Messages : 2273
Enregistré le : lun. 30 mars 2009 22:57
Localisation : Sud-Ouest de la France (43.622788,-1.260864)
Status : Hors ligne

Re: [..] Requêtes SQL

#19

Message par jchd »

Bien, alors je te laisse le temps de mastiquer tout ça et d'apporter les changements qui s'imposent, car forcément j'ai jeté ces bases un peu au pif, ignorant bien des aspects forcément spécifiques à ta problématique.

L'idée principale est de toute façon de bien dissocier les entités et d'expliciter leurs relations, qu'il s'agit ensuite de traduire en relations entre tables. Une base typique pour une application relativement simple peut facilement avoir à contenir plusieurs dizaines de tables et ce n'est pas un problème si elles sont justifiées.

Ce qui n'est pas bon du tout, c'est soit de dissocier par leur contenu des entités de même sémantique (exemple à ne pas suivre : une table de commandes par mois) soit regrouper des choses qui doivent être séparées (autre atrocité : une table des clients, des fournisseurs et du personnel). Dans les deux cas, ça implique de devoir réaliser des opérations compliquées et inutiles dans le code applicatif au lieu de faire faire le boulot proprement par un moteur SQL en général bien plus efficace, piloté par un code compréhensible et maintenable.
La cryptographie d'aujourd'hui c'est le taquin plus l'électricité.
Hugues
Niveau 8
Niveau 8
Messages : 597
Enregistré le : ven. 21 sept. 2012 18:12
Status : Hors ligne

Re: [..] Requêtes SQL

#20

Message par Hugues »

Bon, je reviens à la charge :mrgreen: .

Après une bonne crise de foie et mal de crâne pour digérer tout ça, je commence à comprendre (j'ai bien dit je commence :roll: ) le fonctionnement d'une base SQL (et fichtre que c'est puissant et jouissif pour quelqu'un qui maîtrise ce langage...) .

Bref, j'ai commencé de restructurer selon mes besoins. Pour le moment, je m'occupe de la structure de mes lignes, stations et équipements (la structure que tu proposes me semble très bien, je vais faire l'inventaire de tout ça pour par la suite l'intégrer, mais chaque chose en son temps).

Ce qui est top, c'est la fonction DDL (que je ne connaissais pas) qui permet de "sortir les données voulues", c'est là que je vais creuser un peu, histoire que je comprenne la logique des requêtes...

Dans la base que tu m'as envoyé, il y a une View "Les Postes" dans laquelle il y a la requête:
CREATE VIEW "LesPostes" AS
SELECT [posteid] [ID],
       CASE WHEN [posteid] > 0 THEN [lignenom] || '_' || [stationnom] ELSE [stationnom] END [Poste]
FROM   [postes]
       NATURAL JOIN [lignes]
       NATURAL JOIN [stations]
ORDER  BY [ligneid],
          [stationnom5];
J'ai modifié les noms des tables, nom et colonnes et je voudrais faire afficher une colonne "Ligne" et une colonne "Station", déjà je bloque là dessus... :evil:

Je joins ma base version "demo", elle est uniquement remplie au niveau de mes lignes et stations. J'ai remplacé le nom de la tables "Postes" par "Architecture", et mis des noms "anglophones" :lol:

Base SQLite démo

Merci par avance.
Répondre