Reputation: 3519
I have the following query that works fine:
SELECT NomComplet, IIF(Count(FS3.Index) = 0, '0 (RAS)', Count(FS3.Index))
FROM ControleAcces INNER JOIN (
Employes LEFT JOIN (
SELECT FS1.Index, FS1.OTP, FS1.OTP, FS1.Axe, FS1.FaitSaillant, FS1.Utilisateur, FS2.DateInsertion
FROM FaitsSaillants AS FS1 INNER JOIN (
SELECT Axe, Index, Max(FaitsSaillants.DateInsertion) AS DateInsertion
FROM FaitsSaillants
WHERE DateValue(DateInsertion) > #2010-01-01#
AND DateValue(DateInsertion) < #2011-12-31#
GROUP BY Axe, Index
) AS FS2
ON (FS1.DateInsertion = FS2.DateInsertion
AND FS1.Index = FS2.Index)
WHERE FS1.Axe = 'Project' AND FS2.Axe = 'Project'
) AS FS3
ON Employes.CIP = FS3.Utilisateur
)
ON ControleAcces.Valeur = Employes.CIP
GROUP BY NomComplet
ORDER BY NomComplet
Don't bother to fully understand it, all I want it to edit my IIF condition on the first line. Actually, the condition doesn't do much, it checks how many FS3.Index the query returns and concatenate (RAS)
if it's 0. However, in fact, I would like it to check if there is any row in FaitsSaillants
where Axe = 'RAS'
. If the Count() of this is > 0, then the condition is met.
Can I do a subquery into the IIF segment, something like SELECT COUNT(Index) FROM FaitsSaillants WHERE Axe = 'RAS' AND Utilisateur = FS1.Utilisateur
? If the result is 0, then I add the RAS
to my second field's results. If not, it stays Count(FS3.Index)
.
I tried it and while the syntax is correct, the problem is it can't check for the Utilisateur = FS1.Utilisateur
condition because FS1 is in the main query. However, I must check this because this is the only way to be sure that I'm looking for the right thing: it must be the same Utilisateur
whether I'm in the main query or the subquery.
EDIT:
Here is a shorter version of what I tried from the answers/comments below.
SELECT NomComplet, IIf(FS2.AxeCount > 0, "0 (RAS)", count(FS3.index))
FROM ControleAcces INNER JOIN (Employes LEFT JOIN (SELECT FS2.AxeCount, FS1.Index, FS1.OTP, FS1.OTP, FS1.Axe, FS1.FaitSaillant, FS1.Utilisateur, FS2.DateInsertion
FROM FaitsSaillants AS FS1 INNER JOIN (
SELECT Axe, Index, Max(FaitsSaillants.DateInsertion) AS DateInsertion, SUM(IIf(Axe = 'RAS', 1, 0)) As AxeCount
FROM FaitsSaillants
GROUP BY Axe, Index
) AS FS2
ON (FS1.DateInsertion = FS2.DateInsertion
AND FS1.Index = FS2.Index)
) AS FS3 ON Employes.CIP = FS3.Utilisateur) ON ControleAcces.Valeur = Employes.CIP
GROUP BY NomComplet;
I still got an error about FS2.AxeCount that isn't a part of the aggregate function (iff).
I've also tried this:
SELECT NomComplet, IIf((select count(*) from FaitsSaillants where axe='RAS' and Utilisateur=ControleAcces.Valeur) > 0, "0 (RAS)", count(FS3.index))
FROM ControleAcces INNER JOIN (Employes LEFT JOIN (SELECT FS2.AxeCount, FS1.Index, FS1.OTP, FS1.OTP, FS1.Axe, FS1.FaitSaillant, FS1.Utilisateur, FS2.DateInsertion
FROM FaitsSaillants AS FS1 INNER JOIN (
SELECT Axe, Index, Max(FaitsSaillants.DateInsertion) AS DateInsertion, SUM(IIf(Axe = 'RAS', 1, 0)) As AxeCount
FROM FaitsSaillants
GROUP BY Axe, Index
) AS FS2
ON (FS1.DateInsertion = FS2.DateInsertion
AND FS1.Index = FS2.Index)
) AS FS3 ON Employes.CIP = FS3.Utilisateur) ON ControleAcces.Valeur = Employes.CIP
GROUP BY NomComplet, ControleAccess.Valeur;
Upvotes: 1
Views: 5183
Reputation: 112512
FS3.Index
is NULL if there is no corresponding record, because of the LEFT JOIN. Wouldn't a test
IIf(IsNull(FS3.Index), ..., ...)
... be sufficient? I'm not sure so, since other conditions and joins are involved as well.
UPDATE (recaptulation of comments)
We can get the desired count (AxeCount) from the innermost nested SELECT (FS2):
SELECT
Axe, Index, Max(FaitsSaillants.DateInsertion) AS DateInsertion,
SUM(IIf(Axe = 'RAS', 1, 0)) As AxeCount
FROM FaitsSaillants
...
This intermediate result must be passed to the outermost SELECT by including it in the select list of the intermediate SELECT (FS3):
SELECT FS2.AxeCount, FS1.Index, ...
The outer most SELECT has a GROUP BY clause. In this case, all fields of the select list must either be included in the GROUP BY clause or must be included in an aggregate function. The GROUP BY clause groups rows by the fields listed in this very clause. This usually reduces the number of rows, as several rows similar in their group fields are condensed to form one row. This means that the values of the remaining fields of the select list (not in the group fields) must be combined together. This is what the aggregate function does. Aggregate functions are
See SQL Aggregate Functions (Access)
Now, we can add this in the outermost select list
IIf(SUM(FS2.AxeCount) > 0, ..., ...)
Upvotes: 1
Reputation: 2925
I'm a little unclear on exactly what you want to check in the FaitsSaillants table; you said:
I would like it to check if there is any row in FaitsSaillants where Axe = 'RAS'. If the Count() of this is > 0, then the condition is met.
But you also stated:
something like SELECT COUNT(Index) FROM FaitsSaillants WHERE Axe = 'RAS' AND Employes.CIP = FS3.Utilisateur
My guess is that you meant SELECT COUNT(Index) FROM FaitsSaillants WHERE Axe = 'RAS'
, because in the second SQL statement you're joining to two tables that aren't being referenced in the FROM
clause of your subquery.
What about using DCount
in your IIF statement?
IIF(DCount("Index", "FaitsSaillants", "Axe='RAS'"), '0 (RAS)', Count(FS3.Index))
This should work if you meant SELECT COUNT(Index) FROM FaitsSaillants WHERE Axe = 'RAS'
, but it would need to be modified if you had something else in mind.
Just a caveat though: I would try to use the "domain" functions (DCount, DLookup, etc...) sparingly, because they are slow.
By the way, I believe you can also use a subquery in your IIF statement (is it giving you an error? It seems to work for me):
IIF((SELECT COUNT(*) FROM FaitsSaillants WHERE Axe = 'RAS'), '0 (RAS)', Count(FS3.Index))
Just make sure you are putting the subquery in parenthesis.
Upvotes: 1