Thanks again for taking the time to spell out the detail, it has been very
helpful. I should point out that the original data comes from a download
file
from our ERP system but is not raw data but rather has already been
partially
summarised by running through a report and therefore is "de-normalised" to
an
extent. For instance, I don't get a transaction date, rather the data is
summarised by fiscal week and year. Hence I have tried to "normalise" it
by
setting up a table that cross references the fiscal week and year with a
single date which is why I refer to the source data below as coming from a
query.
I've followed the steps you outlined and here are the results -
Source Data - qryNSalesData
ID LocCode ChWidth WeekDate RevItem QtyCheesesNormLength
2205 02 250 13-Dec-04 01533 6 1000
11947 02 250 07-Mar-05 01533 24 1000
Virtual Table - results as expected
LocCode RevItem ChWidth NormLength BeginMonth EndMonth
02 01533 250 1000 01-Oct-04 31-Oct-04
02 01533 250 1000 01-Nov-04 30-Nov-04
02 01533 250 1000 01-Dec-04 31-Dec-04
02 01533 250 1000 01-Jan-05 31-Jan-05
02 01533 250 1000 01-Feb-05 28-Feb-05
02 01533 250 1000 01-Mar-05 31-Mar-05
02 01533 250 1000 01-Apr-05 30-Apr-05
02 01533 250 1000 01-May-05 31-May-05
02 01533 250 1000 01-Jun-05 30-Jun-05
SQL-
SELECT [qryDistGrps].[LocCode], [qryDistGrps].[RevItem],
[qryDistGrps].[ChWidth], [qryDistGrps].[NormLength],
[qryEnumDates].[BeginMonth], [qryEnumDates].[EndMonth]
FROM qryDistGrps, qryEnumDates
ORDER BY [qryDistGrps].[LocCode], [qryDistGrps].[RevItem],
[qryEnumDates].[BeginMonth], [qryEnumDates].[EndMonth];
Totals Query - still excludes 0 values
LocCode RevItem ChWidth NormLength MY SumTotal
02 01533 250 1000 01-Dec-04 6
02 01533 250 1000 01-Mar-05 24
SQL-
SELECT [qryVirtTbl].[LocCode], [qryVirtTbl].[RevItem],
[qryVirtTbl].[ChWidth], [qryVirtTbl].[NormLength],
[qryVirtTbl].[BeginMonth]
AS MY, Sum(Nz([qryNSalesData].[QtyCheeses],0)) AS SumTotal
FROM qryVirtTbl LEFT JOIN qryNSalesData ON
([qryVirtTbl].[NormLength]=[qryNSalesData].[NormLength]) AND
([qryVirtTbl].[RevItem]=[qryNSalesData].[RevItem]) AND
([qryVirtTbl].[ChWidth]=[qryNSalesData].[ChWidth]) AND
([qryVirtTbl].[LocCode]=[qryNSalesData].[LocCode]) AND
((([qryNSalesData].[WeekDate])>=[qryVirtTbl].[BeginMonth] And
([qryNSalesData].[WeekDate])<[qryVirtTbl].[EndMonth]+1))
GROUP BY [qryVirtTbl].[LocCode], [qryVirtTbl].[ChWidth],
[qryVirtTbl].[RevItem], [qryVirtTbl].[NormLength],
[qryVirtTbl].[BeginMonth]
ORDER BY [qryVirtTbl].[LocCode], [qryVirtTbl].[RevItem];
I'm pretty sure I followed your inst to the letter. If I take out the date
comparison clause I get the below -
LocCode RevItem ChWidth NormLengthMY SumTotal
02 01533 250 1000 01-Oct-04 30
02 01533 250 1000 01-Nov-04 30
02 01533 250 1000 01-Dec-04 30
02 01533 250 1000 01-Jan-05 30
02 01533 250 1000 01-Feb-05 30
02 01533 250 1000 01-Mar-05 30
02 01533 250 1000 01-Apr-05 30
02 01533 250 1000 01-May-05 30
02 01533 250 1000 01-Jun-05 30
Have I missed something ?
Thanks
Gary Walter said:
:
I got as far as the second query - qryRlgAvg and discovered a missing
peice
that may affect the end result. My existing calculation for this
algorithm in
Excel will produce 6 averages even if there are not a full 7 sequential
months of sales data. This is so that I can assign 6 'strengths' to
complete
the final part of the equation as it has been given to me ie count the
A's,
count the B's count the C's etc.
I suspect the first query will need to be modified to show a sumTotal
for
each month even if there is no data for that particular month so that I
can
show a value for each of the 6 avg's even if it =0.
Here is the current SQL-
SELECT [TotalsQry].[LocCode], [TotalsQry].[RevItem],
[TotalsQry].[ChWidth],
Sum([TotalsQry]![#Cheeses]) AS SumTotal,
DateSerial(Year([TotalsQry]![MonthDate]),Month([TotalsQry]![MonthDate]),1)
AS
MY
FROM TotalsQry
WHERE
((([TotalsQry]![MonthDate])>DateSerial(Year(Date()),Month(Date())-8,1)))
GROUP BY [TotalsQry].[LocCode], [TotalsQry].[RevItem],
[TotalsQry].[ChWidth],
DateSerial(Year([TotalsQry]![MonthDate]),Month([TotalsQry]![MonthDate]),1);
Hi,
There may be some more-technical term for this situation,
but I call it "creating something from nothing."
It almost always involves an outer join of "everything possible"
with the real data. Where the real data does not match up,
you NZ a result.
IMHO, this should be done in your TotalsQry.
I believe you want to create a "virtual table" of
every distinct group (possibly LocCode, RevItem, ChWidth?)
and an "associated date" for the time span of 7 months.
Then LEFT JOIN this "virtual table" to your original
data matching on "dates" and Nz'ing 0 values for #Cheeses
where there is no match.
Please provide the SQL for your TotalsQry (plus pertinent table(s),
fields, data types, and example data if possible) and I will try to get
back to help you.
(BTW, I don't believe your use of "bangs," i.e. "!" are
properly applied. I might suggest using "." and restrict the use
of bangs only for objects you have created ...like Forms!frmX!txt1)
*As a guess*, you might have a table "Production" with fields:
LocCode
RevItem
ChWidth
ProdDate
NumCheeses <--BTW, it always end up a bad idea (for me)
when I start out design using any punctuation
(or spaces) in a field name -- like "#Cheeses."
We want a qry that enumerates the last 7 months for each group
(this will be the "virtual table" that we LEFT JOIN to real data).
Let's start with the date part.
Create a table "Iotas" with one Long field "Iota"
and 7 records whose values go from 0 to 6.
Iota
0
1
2
3
4
5
6
So..to enumerate "dates" from the current datemonth
back to the datemonth 6 months ago ,
qryEnumDates
SELECT
DateSerial(Year(Date()),Month(Date())-Iota,1) AS BeginMonth,
DateSerial(Year(Date()),Month(Date())-[Iota]+1,0) AS EndMonth
FROM Iotas;
producing:
qryEnumDates BeginMonth EndMonth
7/1/2005 7/31/2005
6/1/2005 6/30/2005
5/1/2005 5/31/2005
4/1/2005 4/30/2005
3/1/2005 3/31/2005
2/1/2005 2/28/2005
1/1/2005 1/31/2005
lets assume some simple data for data table
Production ProdID LocCode RevItem ChWidth ProdDate NumCheeses
1 A 1 5 1/6/2005 20
2 B 1 5 1/6/2005 25
3 A 1 5 2/9/2005 16
4 B 2 9 2/9/2005 14
5 A 1 5 3/12/2005 31
6 B 1 5 3/12/2005 49
7 A 3 7 4/7/2005 37
8 B 1 5 4/7/2005 42
9 A 1 5 5/15/2005 25
10 B 4 3 5/15/2005 16
11 A 1 5 6/20/2005 37
12 B 1 5 6/20/2005 41
13 A 1 5 7/3/2005 18
what are our distinct "groups?"
SELECT DISTINCT
Production.LocCode,
Production.RevItem,
Production.ChWidth
FROM Production;
qryDistinctGroups LocCode RevItem ChWidth
A 1 5
A 3 7
B 1 5
B 2 9
B 4 3
Our example data gives us 5 distinct groups.
We want our query to produce a "virtual table"
to give us 7 "date" records for each group...
we do this with a Cartesian Join:
SELECT
qryDistinctGroups.LocCode,
qryDistinctGroups.RevItem,
qryDistinctGroups.ChWidth,
qryEnumDates.BeginMonth,
qryEnumDates.EndMonth
FROM qryDistinctGroups, qryEnumDates;
qryVT LocCode RevItem ChWidth BeginMonth EndMonth
A 1 5 7/1/2005 7/31/2005
A 1 5 6/1/2005 6/30/2005
A 1 5 5/1/2005 5/31/2005
A 1 5 4/1/2005 4/30/2005
A 1 5 3/1/2005 3/31/2005
A 1 5 2/1/2005 2/28/2005
A 1 5 1/1/2005 1/31/2005
A 3 7 7/1/2005 7/31/2005
A 3 7 6/1/2005 6/30/2005
A 3 7 5/1/2005 5/31/2005
A 3 7 4/1/2005 4/30/2005
A 3 7 3/1/2005 3/31/2005
A 3 7 2/1/2005 2/28/2005
A 3 7 1/1/2005 1/31/2005
B 1 5 7/1/2005 7/31/2005
B 1 5 6/1/2005 6/30/2005
B 1 5 5/1/2005 5/31/2005
B 1 5 4/1/2005 4/30/2005
B 1 5 3/1/2005 3/31/2005
B 1 5 2/1/2005 2/28/2005
B 1 5 1/1/2005 1/31/2005
B 2 9 7/1/2005 7/31/2005
B 2 9 6/1/2005 6/30/2005
B 2 9 5/1/2005 5/31/2005
B 2 9 4/1/2005 4/30/2005
B 2 9 3/1/2005 3/31/2005
B 2 9 2/1/2005 2/28/2005
B 2 9 1/1/2005 1/31/2005
B 4 3 7/1/2005 7/31/2005
B 4 3 6/1/2005 6/30/2005
B 4 3 5/1/2005 5/31/2005
B 4 3 4/1/2005 4/30/2005
B 4 3 3/1/2005 3/31/2005
B 4 3 2/1/2005 2/28/2005
B 4 3 1/1/2005 1/31/2005
the above could have been accomplished in one query,
but maybe easier to understand this way.
So now we have our "virtual table,"
all that is left is to LEFT JOIN this to "Production"
and sum NumCheeses.
SELECT
Q.LocCode,
Q.RevItem,
Q.ChWidth,
Q.BeginMonth AS MY,
Sum(Nz([NumCheeses],0)) AS SumTotal
FROM qryVT AS Q LEFT JOIN Production AS P
ON
(Q.ChWidth = P.ChWidth)
AND
(Q.RevItem = P.RevItem)
AND
(Q.LocCode = P.LocCode)
AND
(((P.ProdDate)>=[Q].[BeginMonth] And (P.ProdDate)<[Q].[EndMonth]+1))
GROUP BY Q.LocCode, Q.RevItem, Q.ChWidth, Q.BeginMonth;
producing "something from nothing":
qryTotals LocCode RevItem ChWidth MY SumTotal
A 1 5 1/1/2005 20
A 1 5 2/1/2005 16
A 1 5 3/1/2005 31
A 1 5 4/1/2005 0
A 1 5 5/1/2005 25
A 1 5 6/1/2005 37
A 1 5 7/1/2005 18
A 3 7 1/1/2005 0
A 3 7 2/1/2005 0
A 3 7 3/1/2005 0
A 3 7 4/1/2005 37
A 3 7 5/1/2005 0
A 3 7 6/1/2005 0
A 3 7 7/1/2005 0
B 1 5 1/1/2005 25
B 1 5 2/1/2005 0
B 1 5 3/1/2005 49
B 1 5 4/1/2005 42
B 1 5 5/1/2005 0
B 1 5 6/1/2005 41
B 1 5 7/1/2005 0
B 2 9 1/1/2005 0
B 2 9 2/1/2005 14
B 2 9 3/1/2005 0
B 2 9 4/1/2005 0
B 2 9 5/1/2005 0
B 2 9 6/1/2005 0
B 2 9 7/1/2005 0
B 4 3 1/1/2005 0
B 4 3 2/1/2005 0
B 4 3 3/1/2005 0
B 4 3 4/1/2005 0
B 4 3 5/1/2005 16
B 4 3 6/1/2005 0
B 4 3 7/1/2005 0
Again....I have to get ready for work so hope
this will be enough for now...
(I did not verify numbers so I may have made
some dopey mistake)
good luck,
gary