Bonjour,
J'espère que ce petit problème vous intéressera, je cherche à comprendre comment croiser une table avec elle ? voilà où j'en suis arrivé...
La table est constituée comme suit : pour l'exemple nous l'appelerons Table des commandes ->tab_commande
Numéro de client : num_client - type int(4)
date de commande : date_commande - type date
J'ai donc toutes mes données de commandes pour l'année 2004 et pour l'année 2005.
Je cherche tous les clients qui n'ont pas commandé sur une plage de dates par rapport à une plage de dates de référence. Exemple : quels sont les clients qui ont commandé entre le 1/1/2004 et le 31/12/2004 (Periode_1) et qui n'ont pas commandé au mois de janvier 2005 (1/1/2005 au 31/12/2005) Periode_2;
Je remercie au passage l'excellentissime didac de SQLPRO sur la manière de penser le NULL.
Voilà à quoi ressemble ma requête et les questions que je me pose :
SELECT Periode_2.*,Periode_1.* from tab_commande AS Periode_1
LEFT JOIN tab_commande AS Periode_2
ON
Periode_1.num_client=Periode_2.num_client
AND
Periode_1.date_commande BETWEEN '#2004/01/01#'
AND '#2004/12/31#'
AND
Periode_2.date_commande BETWEEN '#2005/01/01#'
AND '#2005/01/31#'
WHERE ISNULL Periode_1
AND
Periode_2.date_commande BETWEEN '#2005/01/01#'
AND '#2005/01/31#'
Je décompose la requête comme je l'ai pensé (à plusieurs...lol) :
Une requête externe gauche afin de récupérer les null de non jointure à la table de droite (la jointure sert ici à récupérer à terme les "non joints" à la table de gauche...).
Comme je ne veux pas que toute la table soit croisée sur elle même, j'ajoute la définition des plages de date dans le join, la jointure externe gauche préservant les non jointures;
Cependant, comme il se peut que certains row retournés soient de la forme :
Periode_2.num_client | Periode_2.date_commande|Periode_1.num_client
4657 2005/02/01 NULL
La clause ON dans laquelle j'ai inclu les between ne tri pas ces dates puisque Periode_1.num_client est null (la jointure externe gauche préserve les NULL, comme SQLPRO l'indique, le NULL n'étant pas une valeur, elle n'est pas 'comparable'), je réinclu donc le même BETWEEN dans la clause WHERE sur Periode_2.date_commande.
Le ISNULL dans la clause WHERE ramenant donc bien les clients n'ayant pas fait de commande sur Periode_2 par rapport à Periode_1.
J'espère avoir été clair... maintenant mes questions :
1 - Optimisation par le moteur de requête :
Les deux clauses BETWEEN dans le ON sont-elles bien prises en compte pour ne croiser que les row des deux périodes concernées ?
Sur une table de plus d'1 million d'enregistrement, je préfèrerais ne demander que le croisement d'un mois avec un autre mois... et pas de toute la table sur elle même...
2 - Position du ISNULL Periode_1
J'ai commancé par le mettre dans le WHERE mais maintenant, je ne sais pas pourquoi, je le placerais bien dans la clause ON (après les deux BETWEEN). J'ai essayé et le résultat n'est pas concluant (résultats erronés), pourquoi ? Quelle différence cela peut-il bien faire qu'il soit placé dans l'une ou dans l'autre position.
Souhaitant avoir aiguisé votre curiosité et vous remerciant par avance du temps forcément nécessaire pour se pencher sur les exemples et les explications des "autres".
Merci d'avance
Partager