Access 2007 left join qui fonctionne comme inner join ???

Access 2007 left join qui fonctionne comme inner join ??? - SQL/NoSQL - Programmation

Marsh Posté le 16-02-2010 à 16:14:23    

bonjour,
 
je mes suis fait sous Access 2007 une base de données de la mort :
une table budget
Code
descriptif
Montant Annuel
Montant 11/09
Montant 12/09
Montant 01/10
Montant 02/10    
[...]
Montant 10/10  
et une table saisie
Date
Pointé
Montant
code
Affectation
 
déjà ça arrache.  :D  
 
Mon but : faire une requete pour comparer mois par mois la différence entre mon budget et mes dépenses.
donc je fais un left join table budget on table saisie sur  "code" (ersatz de code comptable si on veut).
je veux ramener tous mes postes de la table budget et seulement ceux de la table saisie.
tout marche bien jusqu'à ce que je restreigne à l'intervalle de date
Voici le code

Citation :

SELECT Budget.Code, Budget.descriptif, Budget.[Montant 01/10] AS [budget 01/10], Sum(Saisie.Montant) AS [dépense 01/10], (Budget.[Montant 01/10])-Sum(Saisie.Montant) AS différence
FROM Budget LEFT JOIN Saisie ON Budget.Code=Saisie.code
WHERE (((Saisie.date) Between #1/1/2010# And #1/31/2010#))
GROUP BY Budget.Code, Budget.descriptif, Budget.[Montant 01/10];


et la il ne me ramène que les champs pour lesquels j'ai quelque chose dans la table saisie. alors que si je ne met pas de where sur la date, le left join fonctionne....
 
si vous avez une idée avant que je sois obligé d'acheter Money.... :jap:  

Reply

Marsh Posté le 16-02-2010 à 16:14:23   

Reply

Marsh Posté le 17-02-2010 à 09:17:30    

Ben c'est normal : tu mets un condition sur un champ qui appartient à la table Saisie. Donc tous les enregistrements retournés doivent satisfaire cette condition. Essayes en mettant la conditions dans le having et tu précise que la date peut être soit comprise dans l'intervalle soit être nulle.


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 17-02-2010 à 09:28:19    

ce qui reste logique, car si les lignes ne matchent pas, Saisie.date = null, et donc n'est pas en janvier 2010

Reply

Marsh Posté le 17-02-2010 à 11:52:16    

merci Rufo d'avoir pris le temps de regarder.
peux tu me préciser la syntaxe du Having ? car le having n'est que sur une opération pas sur une restriction...
Casimimir, j'avais essayé un isnull(a,b) mais sous access ça n'a pas l'air d'être implémenté

Reply

Marsh Posté le 17-02-2010 à 11:57:08    

RTFM :kaola:  
 
Allé, je suis sympa, je te donne le lien : http://office.microsoft.com/fr-fr/ [...] 31036.aspx


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 17-02-2010 à 17:51:47    

Rufo, j'ai regardé le lien, c'est ce que je te disais, le having ne peut porter que sur une opération pas sur des intervalle de date.
j'ai essayé dans le where de spécifier la date null,  c'est mieux mais ça ne me remonte pas tout.
 
WHERE (Saisie.date Between #1/11/2009# And #11/30/2009# or saisie.date is null)

Reply

Marsh Posté le 18-02-2010 à 09:43:16    

Access 2007 est pas capable de faire ça ???
SELECT Budget.Code, ..., Saisie.date, ... FROM ... HAVING (Saisie.date >= 1/11/2009 AND Saisie.date <= 11/30/2009) OR (Saisie.date IS NULL)...
 
Ca m'étonnerait beaucoup, en MySQL, ça passe tranquille :/ En plus, quand tu lis la doc, c'est bien précisé que ça fonctionne :

Citation :


La clause HAVING est facultative.
 
HAVING est similaire à WHERE, qui détermine quels sont les enregistrements à sélectionner. Une fois que GROUP BY a regroupé les enregistrements, HAVING détermine quels sont les enregistrements qui seront affichés :
 
SELECT RéfCatégorie,
Sum(UnitésEnStock)
FROM Produits
GROUP BY RéfCatégorie
HAVING Sum(UnitésEnStock) > 100 And Like "BOS*";
 
Une clause HAVING peut contenir jusqu'à 40 expressions liées par des opérateurs logiques comme And et Or.


Donc RTFM et apprends à lire!   :sarcastic:
 
EDIT : et je suis sûr qu'on peut remplacer mes >= et <= par un BETWEEN qui est normalement considéré comme un opérateur logique.

Message cité 1 fois
Message édité par rufo le 18-02-2010 à 09:44:08

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 18-02-2010 à 10:00:50    

rufo a écrit :

Access 2007 est pas capable de faire ça ???
SELECT Budget.Code, ..., Saisie.date, ... FROM ... HAVING (Saisie.date >= 1/11/2009 AND Saisie.date <= 11/30/2009) OR (Saisie.date IS NULL)...
 
Ca m'étonnerait beaucoup, en MySQL, ça passe tranquille :/ En plus, quand tu lis la doc, c'est bien précisé que ça fonctionne :

Citation :


La clause HAVING est facultative.
 
HAVING est similaire à WHERE, qui détermine quels sont les enregistrements à sélectionner. Une fois que GROUP BY a regroupé les enregistrements, HAVING détermine quels sont les enregistrements qui seront affichés :
 
SELECT RéfCatégorie,
Sum(UnitésEnStock)
FROM Produits
GROUP BY RéfCatégorie
HAVING Sum(UnitésEnStock) > 100 And Like "BOS*";
 
Une clause HAVING peut contenir jusqu'à 40 expressions liées par des opérateurs logiques comme And et Or.


Donc RTFM et apprends à lire!   :sarcastic:
 
EDIT : et je suis sûr qu'on peut remplacer mes >= et <= par un BETWEEN qui est normalement considéré comme un opérateur logique.


 
rufo pas la peine d'être si désagréable, si je pose la question c'est que j'ai lu et fait des recherches. et que j'ai testé....
 
lis quelques forum commme celui là :
http://sqlpro.developpez.com/cours/sqlaz/ensembles/
 

Citation :

Vous trouverez des compléments d'information sur le sujet aux pages 153 à 154 de l'ouvrage "SQL", collection "La Référence", Campus Press éditeur.
 
La clause HAVING agit comme le filtre WHERE, mais permet de filtrer non plus les données, mais les opérations résultant des regroupements, c'est à dire très généralement toute expression de filtre devant introduire un calcul d'agrégation.
 
Pour tenter de comprendre l'utilité de la clause having, nous allons procéder par un exemple simple : recherchons un étage de l'hôtel capable de coucher au moins 20 personnes.
Partant de notre exemple 2, nous serions tenter d'écrire :
 
Exemple 6
 
SELECT SUM(CHB_COUCHAGE) AS NOMBRE, CHB_ETAGE FROM T_CHAMBRE WHERE SUM(CHB_COUCHAGE) >= 20 GROUP BY CHB_ETAGE
 
Mais cette requête va imanquablement provoquer une erreur avant exécution du fait de la clause WHERE. En effet, souvenons nous que le filtre WHERE agit sur les données des tables et permet de filtrer ligne après ligne. Or le filtrage ne porte plus sur la notion de lignes, mais sur une notion de sous ensemble de la table. En d'autre termes, le filtre, ici, doit porter sur chacun des groupes. C'est pourquoi SQL introduit le filtre HAVING qui porte, non pas sur les données, mais sur les calculs résultants des regroupements.
 
En l'occurence, dans notre exemple, nous devons déporter le filtre WHERE dans la clause HAVING et l'opération deviendra possible :


 
donc je te retourne le RTFM

Reply

Marsh Posté le 18-02-2010 à 10:15:01    

Attends t'es gentil, si je t'ai donné cette solution avec le having, c'est par ce que je l'ai déjà mise en oeuvre dans mon soft Astres (cf ma signature) et que ça marche très bien. Donc soit t'as pas fait la bonne requête, soit Access 2007 est pourri et n'implémente pas correctement la norme SQL (ce qui ne m'étonnerait pas quand on sait que Access 97 ou 2000 ne savait pas fait un COUNT(DISTINCT...)).
 
Montres un peu ta requêtes pour voir si ça viendrait  pas de là?


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 18-02-2010 à 10:43:35    


 
Ne nous énervons pas : tout le monde ment
 
donc voici le code
 

Citation :


SELECT  
Budget.Code,  
Budget.descriptif,  
Budget.[Montant 11/09] AS [budget 11/09],  
Sum(Saisie.Montant) AS [dépense 11/09],  
(Budget.[Montant 11/09])-Sum(Saisie.Montant) AS différence
FROM Budget LEFT JOIN Saisie ON Budget.Code=Saisie.code
WHERE (Saisie.date Between #1/11/2009# And #11/30/2009# or saisie.date is null)
GROUP BY Budget.Code, Budget.descriptif, Budget.[Montant 11/09]
ORDER BY budget.code;


 
or ce qui est bizarre c'est qu'avec le  or saisie.date is null il me ramene bien des champs de ma table budget sans équivalence dans la table saisie (ce que je veux) mais pas tous...

Reply

Marsh Posté le 18-02-2010 à 10:43:35   

Reply

Marsh Posté le 18-02-2010 à 11:09:39    

le code semble correct, il y a juste le Budget.[Montant 11/09]  que je trouve étrange de retrouver dans le group by.
 
 
quand tu dis "mais pas tous...", tu parles de champs ou de lignes?

Reply

Marsh Posté le 18-02-2010 à 11:26:49    

en fait Budget.[Montant 11/09] ne comporte qu'une ligne par code.
donc c'est obligatoire de le mettre dans le group by puisqu'il fait partie du select.
 
et je parle bien de lignes, je peux faire une copie écran du resultat de la requete mais je ne sais pas sur quel site la déposer pour faire le lien dans le forum.

Reply

Marsh Posté le 18-02-2010 à 11:26:53    

MonGhost a écrit :


 
Ne nous énervons pas : tout le monde ment
 
donc voici le code
 

Citation :


SELECT  
Budget.Code,  
Budget.descriptif,  
Budget.[Montant 11/09] AS [budget 11/09],  
Sum(Saisie.Montant) AS [dépense 11/09],  
(Budget.[Montant 11/09])-Sum(Saisie.Montant) AS différence
FROM Budget LEFT JOIN Saisie ON Budget.Code=Saisie.code
WHERE (Saisie.date Between #1/11/2009# And #11/30/2009# or saisie.date is null)
GROUP BY Budget.Code, Budget.descriptif, Budget.[Montant 11/09]
ORDER BY budget.code;


 
or ce qui est bizarre c'est qu'avec le  or saisie.date is null il me ramene bien des champs de ma table budget sans équivalence dans la table saisie (ce que je veux) mais pas tous...


 
Moi, je te demandais la requête avec le having, cette que tu dis qui le fonctionne pas.
 
EDIT : si t'as moyen de changer la structure de ta BD, ça serait pas mal, parce qu'avoir un champ de budget par mois, c'est n'importe quoi :/


Message édité par rufo le 18-02-2010 à 11:28:44

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 18-02-2010 à 11:35:56    

Rufo, si je fais un budget par mois, c'est une bonne partie de mes dépenses ne sont pas récurrentes et arrivent sur un mois en particulier...
 
pour le code avec le having que j'ai testé le voici
 

Citation :

SELECT Budget.Code, Budget.descriptif, Budget.[Montant 11/09] AS [budget 11/09], Sum(Saisie.Montant) AS [dépense 11/09], (Budget.[Montant 11/09])-Sum(Saisie.Montant) AS différence
FROM Budget LEFT JOIN Saisie ON Budget.Code=Saisie.code
where saisie.date between #1/11/2009# And #11/30/2009#
 
having (isnull(Sum(Saisie.Montant),0))
 
 
GROUP BY Budget.Code, Budget.descriptif, Budget.[Montant 11/09]
ORDER BY budget.code;


Message édité par MonGhost le 18-02-2010 à 11:36:25
Reply

Marsh Posté le 18-02-2010 à 11:51:00    

Tu m'étonnes que ça marche pas, c'est n'importe quoi ta requête! C'est pas du tout ce que je t'avais dit de faire.  :sarcastic:  

Code :
  1. SELECT Budget.Code, Budget.descriptif, Budget.[Montant 11/09] AS [budget 11/09], Sum(Saisie.Montant) AS [dépense 11/09], (Budget.[Montant 11/09])-Sum(Saisie.Montant) AS différence
  2. FROM Budget LEFT JOIN Saisie ON Budget.Code=Saisie.code
  3. HAVING (Saisie.date >= 1/11/2009 AND Saisie.date <= 11/30/2009) OR (Saisie.date IS NULL)
  4. GROUP BY Budget.Code, Budget.descriptif, Budget.[Montant 11/09]
  5. ORDER BY budget.code;


Message édité par rufo le 18-02-2010 à 11:51:08

---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 18-02-2010 à 11:59:47    

j'ai essayé ton code, ça me retourne erreur de syntaxe dans la clause Having, comme tu le disais l'implémentation du SQL par Access est un  peu pourrie.
 
merci d'avoir regardé, je poursuis mes recherches

Reply

Marsh Posté le 18-02-2010 à 12:02:13    

Encadre les dates avec des # (pas franchement standard, ça, comme syntaxe :/)


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 18-02-2010 à 12:07:15    

j'avais déjà corrigé les #, mais le message d'erreur est le même

Reply

Marsh Posté le 18-02-2010 à 12:52:12    

Corrige aussi dans le group by Budget.Code, Budget.descriptif, Budget.[Montant 11/09] en group by Budget.Code, Budget.descriptif, [budget 11/09]


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 18-02-2010 à 13:29:19    

il n'y a pas de raisons de mettre le filtre dans un having, ca doit aller dans le where.
 
monghost: si ca ne retourne pas des lignes que tu "désirerais", c'est qu'elle ne correspondent pas avec ton filtre, la c'est a toi de voir le pourquoi du comment par rapport a ton jeu de donnée,  
et en fait en relisant ton truc, ton filtre "(Saisie.date >= 1/11/2009 AND Saisie.date <= 11/30/2009)" devrait se trouver dans ta jointure left outer join, et du coup tu n'aurais plus besoin de tester si la valeur est nulle

Reply

Marsh Posté le 18-02-2010 à 13:37:50    

casimimir a écrit :

il n'y a pas de raisons de mettre le filtre dans un having, ca doit aller dans le where.
 
monghost: si ca ne retourne pas des lignes que tu "désirerais", c'est qu'elle ne correspondent pas avec ton filtre, la c'est a toi de voir le pourquoi du comment par rapport a ton jeu de donnée,  
et en fait en relisant ton truc, ton filtre "(Saisie.date >= 1/11/2009 AND Saisie.date <= 11/30/2009)" devrait se trouver dans ta jointure left outer join, et du coup tu n'aurais plus besoin de tester si la valeur est nulle


 
j'ai essayé ça :
 

Citation :

SELECT  
Budget.Code,  
Budget.descriptif,  
Budget.[Montant 11/09] AS [budget 11/09],  
Sum(Saisie.Montant) AS [dépense 11/09],  
(Budget.[Montant 11/09])-Sum(Saisie.Montant) AS différence
 
FROM Budget LEFT outer JOIN Saisie ON Budget.Code=Saisie.code and saisie.date between #11/1/2009# AND  #11/30/2009#
 
 
GROUP BY Budget.Code, Budget.descriptif, Budget.[Montant 11/09]
 
ORDER BY budget.code;


 
mais j'ai "expression join non supportée".... :fou:  
Access est vraiment naze au niveau SQL
 
je vais regarder mon jeu de données mais ça me parait incohérent de prime abord
 

Reply

Marsh Posté le 18-02-2010 à 14:05:54    

pas terrible access si il ne supporte pas ce type de critère dans le join :)

 

pour moi le seul truc ou tu pourrais rater des lignes avec le filtre que j'avais donné dans le where, serait que dans saisie.date tu aies une date heure, et donc tu raterais tout ce qui est en date du #11/30/2009# et au moins une seconde dans ton exemple.


Message édité par casimimir le 18-02-2010 à 14:06:23
Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed