Bonjour à tous,
Pour commencer, sachez que j'utilise le système de gestion de base de Données d'Ensemble, à savoir Caché.
Ensemble est en quelque sorte un BUS permettant à plusieurs logiciels de communiquer entre eux.
Celui-ci est construit sur la base de Caché qui permet à la fois la gestion de base de données relationnelles et orientées objet...
Il y a beaucoup à dire sur ces systèmes complexes. La doc (lien) vous renseignera mieux que moi si nécessaire.
Sachez juste que Caché embarque SQL incluant tous ces standards : source.
J'ai pris pour habitude de communiquer avec mes DB en full SQL. C'est la raison qui m'amène sur ce forum.
J'ai tenté une requête pour isoler et mettre en parallèle les articles à priori communs entre deux "bases articles". Une base articles reprend un ensemble d'articles propres à un type de commerce.
Je vous préviens à l'avance, la base de données est vieille, très vieille, et les transgressions aux propriétés ACID y sont nombreuses, ainsi que les erreurs pures et simples d'architecture relationnelle. On ne retrouve par exemple aucune clé primaire ou étrangères. Les liens se font généralement sur un ou plusieurs champs arbitraires. Mais dans un soucis de coller à la réalité, je vais montrer des requêtes très proches de ce qui s'y fait.
Voici la définition de mes deux tables :
Voici un exemple d'échantillon :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 -- Articles reprend les données signalétiques des articles qui sont propres à une base articles (un type de commerce) CREATE TABLE IF NOT EXISTS Articles ( BaseArticles INT, CodeArticle VARCHAR(10), BarCode VARCHAR(15), LibelléArticle VARCHAR(50) -- Autres propriétés ); -- ArtFou reprend les données signalétiques des articles qui sont propres à un fournisseur et un dépôt (un magasin) CREATE TABLE IF NOT EXISTS ArtFou ( BaseArticles INT, CodeArticle VARCHAR(10), CodeArtFou VARCHAR(15), CodeFournisseur VARCHAR(10), CodeDépôt INT -- Autres propriétés );
Voici la requête SELECT :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 INSERT INTO Articles (BaseArticles, CodeArticle, BarCode, LibelléArticle) VALUES (95, 'A', '1', 'Article n°1'), (95, 'D', NULL, 'Article n°4'), (95, 'E', '5', 'Article n°5'), (95, 'G', NULL, 'Article n°7'), (95, 'I', '8', 'Article n°8'), (95, 'J', '10', 'Article n°10'), (17, 'E', '5', 'Article n°5'), (17, 'G', '7', 'Article n°7'), (17, 'H', '8', 'Article n°8'), (17, 'I', '9', 'Article n°9'), (17, 'J', NULL, 'Article n°10'), (17, 'P', '16', 'Article n°16'); INSERT INTO ArtFou (BaseArticles, CodeArticle, CodeArtFou, CodeFournisseur, CodeDépôt) VALUES (95, 'A', 'F1-1', 'F1', 0), (95, 'E', 'F1-2', 'F1', 0), (95, 'G', 'F3-1', 'F3', 0), (95, 'I', 'F3-2', 'F3', 0), (95, 'J', 'F3-3', 'F3', 0), (17, 'E', 'F1-2', 'F1', 0), (17, 'G', 'F4-2', 'F4', 0), (17, 'J', NULL, 'F4', 0);
L'idée derrière cette requête c'est de retrouver tous les articles des bases 17 et 95 avec leur homologues de l'autre base articles, sans oublier les articles pour lesquels on a trouvé aucune correspondance.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 SELECT -- Base 95 Base95.CodeArticle AS CodeArticle95, Base95.Barcode AS BarCode95, Base95.CodeArtFou AS CodeArtFou95, Base95.LibelléArticle AS LibelléArticle95, -- Base 17 Base17.CodeArticle AS CodeArticle17, Base17.Barcode AS BarCode17, Base17.CodeArtFou AS CodeArtFou17, Base17.LibelléArticle AS LibelléArticle17 FROM ( -- Base 95 SELECT Articles.CodeArticle, Articles.Barcode, ArtFou.CodeArtFou, Articles.LibelléArticle FROM Articles LEFT JOIN ArtFou ON (Articles.BaseArticles = ArtFou.BaseArticles AND Articles.CodeArticle = ArtFou.CodeArticle AND ArtFou.CodeDépôt = '0') WHERE Articles.BaseArticles = '95' ) AS Base95 FULL JOIN ( -- Base 17 SELECT Articles.CodeArticle, Articles.Barcode, ArtFou.CodeArtFou, Articles.LibelléArticle FROM Articles LEFT JOIN ArtFou ON (Articles.BaseArticles = ArtFou.BaseArticles AND Articles.CodeArticle = ArtFou.CodeArticle AND ArtFou.CodeDépôt = '0') WHERE Articles.BaseArticles = '17' ) AS Base17 ON (Base95.CodeArtFou = Base17.CodeArtFou OR Base95.CodeArticle = Base17.CodeArticle /*OR Base95.Barcode = Base17.Barcode*/)
Un article est l'homologue d'un autre lorsque au moins un des éléments suivants est semblable:
- CodeArticle
- BarCode
- CodeArtFou
Voici une idée du résultat attendu :
BaseArticles95 CodeArticle95 BarCode95 LibelléArticle95 CodeArtFou95 BaseArticles17 CodeArticle17 BarCode17 LibelléArticle17 CodeArtFou17 95 A 1 Article n°1 F1-1 95 D Article n°4 95 I 8 Article n°8 F3-2 17 I 9 Article n°9 95 I 8 Article n°8 F3-2 17 H 8 Article n°8 95 E 5 Article n°5 F1-2 17 E 5 Article n°5 F1-2 95 G Article n°7 F3-1 17 G 7 Article n°7 F4-2 95 J 10 Article n°10 F3-3 17 J Article n°10 17 P 16 Article n°16
L'exécution de cette requête plante dans mon SGBD.
La jointure externe n'est pas reconnue.
J'ai isolé la ligne qui pose problème (la dernière, en commentaire, dans le 'ON').
En fait, pour être tout à fait précis, l’erreur vient du fait que je fais une jointure externe avec l’opérateur ‘OR’ sur plusieurs champs issus de plus d’une table contenue dans mes sous-requêtes… C'est très pointu...
Avec l’opérateur ‘AND’ dans le 'ON', pas de problème.
Avec seulement les champs provenant de la table ‘Articles’ de mes sous-requête, mais l’opérateur ‘OR’, pas de problème
Avec la même jointure mais en INNER JOIN, pas de problème.
Ai-je atteint une limite du SQL ?
Est-ce du à mon SGBD, à son optimiseur ?
Avez-vous une syntaxe alternative ?
Je vous remercie d'avance pour le temps que vous prendrez à essayer de résoudre mon problème.
Bien à vous,
Partager