Help with calculations in a query

R

RWhittet

I have run into a problem in my query. I am trying to run calculations on
water meters. I have been able to calculate the information I need on my
forms, by using DLookup, but it's a bit more tricky to do in the query.
These meters are read everyday, and the calculations needed are also daily as
they convert the value into million gallons per day. The calculation is as
follows;
(Day 2 meter reading - Day 1 meter reading)/1000

All of the readings are stored in the same table, so the biggest problem is
referencing the value from the previous record. I have also been able to
create the calculations in my reports, but I'm unable to use a monthly
average or sum on a calculated field in a report. Any solutions or
suggestions would be greatly appreciated!

Richard Whittet
 
A

Allen Browne

If you don't mind read-only results, it is probably quicker to use a
subquery to get the prior meter reading. Something like this:

SELECT ID, MeterID, ReadingDate, Reading
(SELECT TOP 1 REeading FROM tblReading AS Dupe
WHERE Dupe.MeterID = tblReading.MeterID
AND Dupe.ReadingDate < tblReading.ReadingDate
ORDER BY Dupe.ReadingDate, Dupe.ID) AS PriorReading
FROM tblReading;

That assumes the table is named tblReading, and the primary key is ID.

Having created that query, you should be able to use it as a source "table"
for another query to calculate the average or sum.

If you notice the numbers in the PriorReading field left-aligning when you
view this query, Access is treating them as text so you need to typcast the
result. More info in:
Calculated fields misinterpreted
at:
http://allenbrowne.com/ser-45.html
 
T

Tom Ellison

Dear Richard:

Before helping prepare a way to query this, I want to check certain facts.

You say, "These meters are read everyday" Does that mean it is never the
case that a day goes by in which no meters are read (a holiday for example)?
Does it mean that it is never the case that a meter is skipped?

If a day is skipped, like a holiday, then are you going to give results for
a 2 day period instead? If a meter is skipped, will you skip reporting that
meter for 2 days (the day in which it has the current reading, then the day
in which it has the previous reading).

Will the user pulling this report select the Day 1 date? Will you then
report only those meter that were read on the chosen date AND on the
previous day?

Realistically, real world data has holes in it. I'm trying to get our
thinking together on whether such holes will EVER happen, and what you want
to do in that case.

In order to do what you want, you need to use two copies of the table in the
same query. One feature of doing this is to alias them, so you can
reference them separately.

I need some detailed, precise information on the questions I asked before I
can begin to craft any solution. OK?

I'm going to suggest one possible solution to the problem. Let's say you
have a control on a form with the more recent date in it. We could then
build a query that filters to that date and to the immediately preceeding
calendar date. Any meter that does not have BOTH readings would be excluded
from the results. That's a simple, but perhaps not most desirable way to
handle it.

Tom Ellison
 
J

John Spencer

If you have one reading for every day then this is fairly simple. If you have
multiple readings or days get skipped then this gets to be a bit more complex.

Simplest case - one reading EVERY day. (Substitute your field and table names)

SELECT A.MeterID, A.ReadingDate, (A.Reading - B.Reading)/1000
FROM YourTable as A INNER JOIN YourTable As B
ON A.ReadingDate = B.ReadingDate -1
AND R.MeterID = B.MeterID

This will return NO record (row) for any case where there is no immediate prior
date. So for instance the oldest record in the table will not be in your list.

By the way, if you can do it with DLookup on a form, you should be able to
transfer that same logic into the query. You could post your DLookup code and
someone may be able to suggest how you can use that to get the desired results.
 
R

RWhittet

Thanks for the quick responses. There will never be a day when the meters
are not read. The only case of an unread meter would be if that pipeline was
taken offline for repairs. And, this has happened. The ultimate goal is to
create a montly sum of the total amount of water through each meter to be
used for billing, budgeting, predictions, etc. But, my boss created a
spreadsheet years ago that has been used ever since, so I am trying to
duplicate it, in a sense. It is important that these calculations be
accurate. The user pulling the report will select the beginning and ending
date. The report itself is designed as a monthly report.

This is the code I have used in my form to show the previous meter reading.

=DLookUp("[South Recycle]","[Meter Usage]","[Date] = Forms![Meter
Usage]![Date]-1")

Richard Whittet
 
R

RWhittet

Is there a way to manipulate this expression to where it will work in the
query? I have been trying different things but it always returns the same
days reading. I think the problem lies in the criteria of the argument.
Also, I'm not good with the SQL language so if you could retype it using my
field and table names that would be great.

Expr1: DLookUp([South Recycle],"Meter Usage",[Day]-1)
 
T

Tom Ellison

Dear Richard:

Something about this makes me vary leary. So, the meter is never out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each will react
differently if a reading is missing for any reason. But I'll go ahead
anyway.

I will use an INNER JOIN between two copies of the table. JOIN it ON the
column that identifies each meter. Filter it with so one table has the
reading date equal to Forms![Meter Usage]!Date and the other to the same
date minus 1. That's at least a starting point.

I don't know the names of your table and columns. Without that I cannot be
more specific.

Any meter for which the two readings are not both present will be omitted
from these results. It doesn't matter what kind of failure may have
produced the missing data.

Frankly, I would have thought to prorate between the reading whenever there
is a missing reading. That is, if the meter read 13 on the first of the
month, and 22 on the fourth, then the consumption on the second, or the
third, or the fourth would each be 3 units.

Before pushing such an idea, I'd use queries to investigate where there is
any history of a meter reading being missing. A simple aggregate of
COUNT(*) for each meter, and a COUNT(*) of every DISTINCT Date value in the
table would tell me if there are missing readings, and how common they are.

Those who instruct us to perform tasks like this often mistake just how
reliable their data is. I wouldn't ever argue such a point except where it
is historically demonstrable. Once you can prove the necessity for a
cautious approach, then management can be made ready to listen.

I hope you won't think I'm being intrusive. This is really the voice of
reason and experience.

Tom Ellison


RWhittet said:
Thanks for the quick responses. There will never be a day when the meters
are not read. The only case of an unread meter would be if that pipeline
was
taken offline for repairs. And, this has happened. The ultimate goal is
to
create a montly sum of the total amount of water through each meter to be
used for billing, budgeting, predictions, etc. But, my boss created a
spreadsheet years ago that has been used ever since, so I am trying to
duplicate it, in a sense. It is important that these calculations be
accurate. The user pulling the report will select the beginning and
ending
date. The report itself is designed as a monthly report.

This is the code I have used in my form to show the previous meter
reading.

=DLookUp("[South Recycle]","[Meter Usage]","[Date] = Forms![Meter
Usage]![Date]-1")

Richard Whittet

Tom Ellison said:
Dear Richard:

Before helping prepare a way to query this, I want to check certain
facts.

You say, "These meters are read everyday" Does that mean it is never the
case that a day goes by in which no meters are read (a holiday for
example)?
Does it mean that it is never the case that a meter is skipped?

If a day is skipped, like a holiday, then are you going to give results
for
a 2 day period instead? If a meter is skipped, will you skip reporting
that
meter for 2 days (the day in which it has the current reading, then the
day
in which it has the previous reading).

Will the user pulling this report select the Day 1 date? Will you then
report only those meter that were read on the chosen date AND on the
previous day?

Realistically, real world data has holes in it. I'm trying to get our
thinking together on whether such holes will EVER happen, and what you
want
to do in that case.

In order to do what you want, you need to use two copies of the table in
the
same query. One feature of doing this is to alias them, so you can
reference them separately.

I need some detailed, precise information on the questions I asked before
I
can begin to craft any solution. OK?

I'm going to suggest one possible solution to the problem. Let's say you
have a control on a form with the more recent date in it. We could then
build a query that filters to that date and to the immediately preceeding
calendar date. Any meter that does not have BOTH readings would be
excluded
from the results. That's a simple, but perhaps not most desirable way to
handle it.

Tom Ellison
 
R

RWhittet

Dear Tom,

After talking about this I am wondering if there isn't a better approach to
this. Lets say that I created an extra field in my table for each meter
reading, and used my calculated controls on the form to set the values of
these fields. I have played around with the set value macro before but I
haven't gotten it to work. If this is possible I think would rather go this
route. The meters we use are pretty sophisticated, they are connected to the
SCADA system, and we also have operators who record the readings daily. Give
this some thought and let me know what you think and if you have any
experience with the set value macro I would appreciate that too.

Thanks,
Richard

Tom Ellison said:
Dear Richard:

Something about this makes me vary leary. So, the meter is never out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each will react
differently if a reading is missing for any reason. But I'll go ahead
anyway.

I will use an INNER JOIN between two copies of the table. JOIN it ON the
column that identifies each meter. Filter it with so one table has the
reading date equal to Forms![Meter Usage]!Date and the other to the same
date minus 1. That's at least a starting point.

I don't know the names of your table and columns. Without that I cannot be
more specific.

Any meter for which the two readings are not both present will be omitted
from these results. It doesn't matter what kind of failure may have
produced the missing data.

Frankly, I would have thought to prorate between the reading whenever there
is a missing reading. That is, if the meter read 13 on the first of the
month, and 22 on the fourth, then the consumption on the second, or the
third, or the fourth would each be 3 units.

Before pushing such an idea, I'd use queries to investigate where there is
any history of a meter reading being missing. A simple aggregate of
COUNT(*) for each meter, and a COUNT(*) of every DISTINCT Date value in the
table would tell me if there are missing readings, and how common they are.

Those who instruct us to perform tasks like this often mistake just how
reliable their data is. I wouldn't ever argue such a point except where it
is historically demonstrable. Once you can prove the necessity for a
cautious approach, then management can be made ready to listen.

I hope you won't think I'm being intrusive. This is really the voice of
reason and experience.

Tom Ellison


RWhittet said:
Thanks for the quick responses. There will never be a day when the meters
are not read. The only case of an unread meter would be if that pipeline
was
taken offline for repairs. And, this has happened. The ultimate goal is
to
create a montly sum of the total amount of water through each meter to be
used for billing, budgeting, predictions, etc. But, my boss created a
spreadsheet years ago that has been used ever since, so I am trying to
duplicate it, in a sense. It is important that these calculations be
accurate. The user pulling the report will select the beginning and
ending
date. The report itself is designed as a monthly report.

This is the code I have used in my form to show the previous meter
reading.

=DLookUp("[South Recycle]","[Meter Usage]","[Date] = Forms![Meter
Usage]![Date]-1")

Richard Whittet

Tom Ellison said:
Dear Richard:

Before helping prepare a way to query this, I want to check certain
facts.

You say, "These meters are read everyday" Does that mean it is never the
case that a day goes by in which no meters are read (a holiday for
example)?
Does it mean that it is never the case that a meter is skipped?

If a day is skipped, like a holiday, then are you going to give results
for
a 2 day period instead? If a meter is skipped, will you skip reporting
that
meter for 2 days (the day in which it has the current reading, then the
day
in which it has the previous reading).

Will the user pulling this report select the Day 1 date? Will you then
report only those meter that were read on the chosen date AND on the
previous day?

Realistically, real world data has holes in it. I'm trying to get our
thinking together on whether such holes will EVER happen, and what you
want
to do in that case.

In order to do what you want, you need to use two copies of the table in
the
same query. One feature of doing this is to alias them, so you can
reference them separately.

I need some detailed, precise information on the questions I asked before
I
can begin to craft any solution. OK?

I'm going to suggest one possible solution to the problem. Let's say you
have a control on a form with the more recent date in it. We could then
build a query that filters to that date and to the immediately preceeding
calendar date. Any meter that does not have BOTH readings would be
excluded
from the results. That's a simple, but perhaps not most desirable way to
handle it.

Tom Ellison


I have run into a problem in my query. I am trying to run calculations
on
water meters. I have been able to calculate the information I need on
my
forms, by using DLookup, but it's a bit more tricky to do in the query.
These meters are read everyday, and the calculations needed are also
daily
as
they convert the value into million gallons per day. The calculation
is
as
follows;
(Day 2 meter reading - Day 1 meter reading)/1000

All of the readings are stored in the same table, so the biggest
problem
is
referencing the value from the previous record. I have also been able
to
create the calculations in my reports, but I'm unable to use a monthly
average or sum on a calculated field in a report. Any solutions or
suggestions would be greatly appreciated!

Richard Whittet
 
T

Tom Ellison

Dear Richard:

Well, Richard, I'll tell you what I do know.

I do know that I've tried various approaches to solving many database
problems. From some successes and failures, I've come to the conclusion
that the rules about how databases should be constructed are extremely
valuable. And these rules say not to store any derived values in tables.
The biggest reason for that is as follows: If you have a derived value, and
any of the stored values that are components of that value are changed, then
the derived value must immediately change as well.

I have actually written the code that will make a derived value follow any
database changes. It is about 5-10 times as much work as doing it
correctly, and it tends to be unreliable. It is too easy to forget one of
the things that might change and make the derived value incorrect.

For example, when you do this, how will you handle the case that a user
deletes the row containing the previous day's reading? How will you handle
it if the user then re-enters that row, but with a different value?

I'm telling you, it's a complex mess handling all these eventualities, if
you write the system incorrectly. However, if you simply derive all the
derived values at the moment you need them, then you won't have this
problem.

Everything in my 23 year's experience writing database software screams that
this is a really bad approach.

The kind of query you need is something I write several times a week, and
have done so hundreds of times. In my own project, this would not take me
15 minutes. I say that not to brag (there are many who post answers here
who have similar experience and capability) but to encourage you to learn
the best skills and to apply them properly. Very soon you'll see that this
becomes easy to handle, and that this is definitely the best way to handle
the situation.

As I see it, you're at a turning point in how you will develop as a database
programmer. If you listen to good advise, and put it into practice, you'll
be vastly better off.

Perhaps others who are experienced and read this will drop in and lend a
vote to what I'm telling you, so you'll see what I say is quite true, and
important. Because what I'm advising you is not my personal preference, but
a very common experience of virtually all who have advanced professionally
in this field.

If you'll expose for me the name of your table and the names of your
columns, and perhaps a bit of sample data, I'll write the query to do this.
I've done so dozens of times per year for 5 or 6 years now in this
newsgroup, and have used this as a tool to teach how this is done to dozens
of others, and with quite good success (I'm guessing more than 95%). You'll
probably be glad you did!

Tom Ellison


RWhittet said:
Dear Tom,

After talking about this I am wondering if there isn't a better approach
to
this. Lets say that I created an extra field in my table for each meter
reading, and used my calculated controls on the form to set the values of
these fields. I have played around with the set value macro before but I
haven't gotten it to work. If this is possible I think would rather go
this
route. The meters we use are pretty sophisticated, they are connected to
the
SCADA system, and we also have operators who record the readings daily.
Give
this some thought and let me know what you think and if you have any
experience with the set value macro I would appreciate that too.

Thanks,
Richard

Tom Ellison said:
Dear Richard:

Something about this makes me vary leary. So, the meter is never out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each will react
differently if a reading is missing for any reason. But I'll go ahead
anyway.

I will use an INNER JOIN between two copies of the table. JOIN it ON the
column that identifies each meter. Filter it with so one table has the
reading date equal to Forms![Meter Usage]!Date and the other to the same
date minus 1. That's at least a starting point.

I don't know the names of your table and columns. Without that I cannot
be
more specific.

Any meter for which the two readings are not both present will be omitted
from these results. It doesn't matter what kind of failure may have
produced the missing data.

Frankly, I would have thought to prorate between the reading whenever
there
is a missing reading. That is, if the meter read 13 on the first of the
month, and 22 on the fourth, then the consumption on the second, or the
third, or the fourth would each be 3 units.

Before pushing such an idea, I'd use queries to investigate where there
is
any history of a meter reading being missing. A simple aggregate of
COUNT(*) for each meter, and a COUNT(*) of every DISTINCT Date value in
the
table would tell me if there are missing readings, and how common they
are.

Those who instruct us to perform tasks like this often mistake just how
reliable their data is. I wouldn't ever argue such a point except where
it
is historically demonstrable. Once you can prove the necessity for a
cautious approach, then management can be made ready to listen.

I hope you won't think I'm being intrusive. This is really the voice of
reason and experience.

Tom Ellison


RWhittet said:
Thanks for the quick responses. There will never be a day when the
meters
are not read. The only case of an unread meter would be if that
pipeline
was
taken offline for repairs. And, this has happened. The ultimate goal
is
to
create a montly sum of the total amount of water through each meter to
be
used for billing, budgeting, predictions, etc. But, my boss created a
spreadsheet years ago that has been used ever since, so I am trying to
duplicate it, in a sense. It is important that these calculations be
accurate. The user pulling the report will select the beginning and
ending
date. The report itself is designed as a monthly report.

This is the code I have used in my form to show the previous meter
reading.

=DLookUp("[South Recycle]","[Meter Usage]","[Date] = Forms![Meter
Usage]![Date]-1")

Richard Whittet

:

Dear Richard:

Before helping prepare a way to query this, I want to check certain
facts.

You say, "These meters are read everyday" Does that mean it is never
the
case that a day goes by in which no meters are read (a holiday for
example)?
Does it mean that it is never the case that a meter is skipped?

If a day is skipped, like a holiday, then are you going to give
results
for
a 2 day period instead? If a meter is skipped, will you skip
reporting
that
meter for 2 days (the day in which it has the current reading, then
the
day
in which it has the previous reading).

Will the user pulling this report select the Day 1 date? Will you
then
report only those meter that were read on the chosen date AND on the
previous day?

Realistically, real world data has holes in it. I'm trying to get our
thinking together on whether such holes will EVER happen, and what you
want
to do in that case.

In order to do what you want, you need to use two copies of the table
in
the
same query. One feature of doing this is to alias them, so you can
reference them separately.

I need some detailed, precise information on the questions I asked
before
I
can begin to craft any solution. OK?

I'm going to suggest one possible solution to the problem. Let's say
you
have a control on a form with the more recent date in it. We could
then
build a query that filters to that date and to the immediately
preceeding
calendar date. Any meter that does not have BOTH readings would be
excluded
from the results. That's a simple, but perhaps not most desirable way
to
handle it.

Tom Ellison


I have run into a problem in my query. I am trying to run
calculations
on
water meters. I have been able to calculate the information I need
on
my
forms, by using DLookup, but it's a bit more tricky to do in the
query.
These meters are read everyday, and the calculations needed are also
daily
as
they convert the value into million gallons per day. The
calculation
is
as
follows;
(Day 2 meter reading - Day 1 meter reading)/1000

All of the readings are stored in the same table, so the biggest
problem
is
referencing the value from the previous record. I have also been
able
to
create the calculations in my reports, but I'm unable to use a
monthly
average or sum on a calculated field in a report. Any solutions or
suggestions would be greatly appreciated!

Richard Whittet
 
R

RWhittet

Tom,

I definitely would like to do this the right way, and any help you can give
me is most appreciated. I haven't had any formal training in database
programming, most of what I've learned has been from trial and error, and it
does take up a lot of time, but at the same time it is the best way for me to
learn something. I will have to get back to you tomorrow with the table
names and the column names, as I don't have the database at home.

Thanks again,
Richard

Tom Ellison said:
Dear Richard:

Well, Richard, I'll tell you what I do know.

I do know that I've tried various approaches to solving many database
problems. From some successes and failures, I've come to the conclusion
that the rules about how databases should be constructed are extremely
valuable. And these rules say not to store any derived values in tables.
The biggest reason for that is as follows: If you have a derived value, and
any of the stored values that are components of that value are changed, then
the derived value must immediately change as well.

I have actually written the code that will make a derived value follow any
database changes. It is about 5-10 times as much work as doing it
correctly, and it tends to be unreliable. It is too easy to forget one of
the things that might change and make the derived value incorrect.

For example, when you do this, how will you handle the case that a user
deletes the row containing the previous day's reading? How will you handle
it if the user then re-enters that row, but with a different value?

I'm telling you, it's a complex mess handling all these eventualities, if
you write the system incorrectly. However, if you simply derive all the
derived values at the moment you need them, then you won't have this
problem.

Everything in my 23 year's experience writing database software screams that
this is a really bad approach.

The kind of query you need is something I write several times a week, and
have done so hundreds of times. In my own project, this would not take me
15 minutes. I say that not to brag (there are many who post answers here
who have similar experience and capability) but to encourage you to learn
the best skills and to apply them properly. Very soon you'll see that this
becomes easy to handle, and that this is definitely the best way to handle
the situation.

As I see it, you're at a turning point in how you will develop as a database
programmer. If you listen to good advise, and put it into practice, you'll
be vastly better off.

Perhaps others who are experienced and read this will drop in and lend a
vote to what I'm telling you, so you'll see what I say is quite true, and
important. Because what I'm advising you is not my personal preference, but
a very common experience of virtually all who have advanced professionally
in this field.

If you'll expose for me the name of your table and the names of your
columns, and perhaps a bit of sample data, I'll write the query to do this.
I've done so dozens of times per year for 5 or 6 years now in this
newsgroup, and have used this as a tool to teach how this is done to dozens
of others, and with quite good success (I'm guessing more than 95%). You'll
probably be glad you did!

Tom Ellison


RWhittet said:
Dear Tom,

After talking about this I am wondering if there isn't a better approach
to
this. Lets say that I created an extra field in my table for each meter
reading, and used my calculated controls on the form to set the values of
these fields. I have played around with the set value macro before but I
haven't gotten it to work. If this is possible I think would rather go
this
route. The meters we use are pretty sophisticated, they are connected to
the
SCADA system, and we also have operators who record the readings daily.
Give
this some thought and let me know what you think and if you have any
experience with the set value macro I would appreciate that too.

Thanks,
Richard

Tom Ellison said:
Dear Richard:

Something about this makes me vary leary. So, the meter is never out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each will react
differently if a reading is missing for any reason. But I'll go ahead
anyway.

I will use an INNER JOIN between two copies of the table. JOIN it ON the
column that identifies each meter. Filter it with so one table has the
reading date equal to Forms![Meter Usage]!Date and the other to the same
date minus 1. That's at least a starting point.

I don't know the names of your table and columns. Without that I cannot
be
more specific.

Any meter for which the two readings are not both present will be omitted
from these results. It doesn't matter what kind of failure may have
produced the missing data.

Frankly, I would have thought to prorate between the reading whenever
there
is a missing reading. That is, if the meter read 13 on the first of the
month, and 22 on the fourth, then the consumption on the second, or the
third, or the fourth would each be 3 units.

Before pushing such an idea, I'd use queries to investigate where there
is
any history of a meter reading being missing. A simple aggregate of
COUNT(*) for each meter, and a COUNT(*) of every DISTINCT Date value in
the
table would tell me if there are missing readings, and how common they
are.

Those who instruct us to perform tasks like this often mistake just how
reliable their data is. I wouldn't ever argue such a point except where
it
is historically demonstrable. Once you can prove the necessity for a
cautious approach, then management can be made ready to listen.

I hope you won't think I'm being intrusive. This is really the voice of
reason and experience.

Tom Ellison


Thanks for the quick responses. There will never be a day when the
meters
are not read. The only case of an unread meter would be if that
pipeline
was
taken offline for repairs. And, this has happened. The ultimate goal
is
to
create a montly sum of the total amount of water through each meter to
be
used for billing, budgeting, predictions, etc. But, my boss created a
spreadsheet years ago that has been used ever since, so I am trying to
duplicate it, in a sense. It is important that these calculations be
accurate. The user pulling the report will select the beginning and
ending
date. The report itself is designed as a monthly report.

This is the code I have used in my form to show the previous meter
reading.

=DLookUp("[South Recycle]","[Meter Usage]","[Date] = Forms![Meter
Usage]![Date]-1")

Richard Whittet

:

Dear Richard:

Before helping prepare a way to query this, I want to check certain
facts.

You say, "These meters are read everyday" Does that mean it is never
the
case that a day goes by in which no meters are read (a holiday for
example)?
Does it mean that it is never the case that a meter is skipped?

If a day is skipped, like a holiday, then are you going to give
results
for
a 2 day period instead? If a meter is skipped, will you skip
reporting
that
meter for 2 days (the day in which it has the current reading, then
the
day
in which it has the previous reading).

Will the user pulling this report select the Day 1 date? Will you
then
report only those meter that were read on the chosen date AND on the
previous day?

Realistically, real world data has holes in it. I'm trying to get our
thinking together on whether such holes will EVER happen, and what you
want
to do in that case.

In order to do what you want, you need to use two copies of the table
in
the
same query. One feature of doing this is to alias them, so you can
reference them separately.

I need some detailed, precise information on the questions I asked
before
I
can begin to craft any solution. OK?

I'm going to suggest one possible solution to the problem. Let's say
you
have a control on a form with the more recent date in it. We could
then
build a query that filters to that date and to the immediately
preceeding
calendar date. Any meter that does not have BOTH readings would be
excluded
from the results. That's a simple, but perhaps not most desirable way
to
handle it.

Tom Ellison


I have run into a problem in my query. I am trying to run
calculations
on
water meters. I have been able to calculate the information I need
on
my
forms, by using DLookup, but it's a bit more tricky to do in the
query.
These meters are read everyday, and the calculations needed are also
daily
as
they convert the value into million gallons per day. The
calculation
is
as
follows;
(Day 2 meter reading - Day 1 meter reading)/1000

All of the readings are stored in the same table, so the biggest
problem
is
referencing the value from the previous record. I have also been
able
to
create the calculations in my reports, but I'm unable to use a
monthly
average or sum on a calculated field in a report. Any solutions or
suggestions would be greatly appreciated!

Richard Whittet
 
J

John Spencer

Well, you are getting much more comprehensive advice from Tom Ellison. If you
can, use his advice.

The DLookup function expects strings for its arguments, so

Expr1: DLookUp("[South Recycle]","[Meter Usage]", "[Day]=#"&
DateDiff("d",-1,[Day]) &"#")

The third argument is basically a WHERE clause without "WHERE" at the beginning
of the clause. It should end up being a string that looks like
"[Day]=#11/12/2005#"

Where 11/12/2005 is one less than the value of Day in the current record.

Like I said work with Tom Ellison - he will help you develop a robust solution
that will take into account the missing data.
Is there a way to manipulate this expression to where it will work in the
query? I have been trying different things but it always returns the same
days reading. I think the problem lies in the criteria of the argument.
Also, I'm not good with the SQL language so if you could retype it using my
field and table names that would be great.

Expr1: DLookUp([South Recycle],"Meter Usage",[Day]-1)

John Spencer said:
If you have one reading for every day then this is fairly simple. If you have
multiple readings or days get skipped then this gets to be a bit more complex.

Simplest case - one reading EVERY day. (Substitute your field and table names)

SELECT A.MeterID, A.ReadingDate, (A.Reading - B.Reading)/1000
FROM YourTable as A INNER JOIN YourTable As B
ON A.ReadingDate = B.ReadingDate -1
AND R.MeterID = B.MeterID

This will return NO record (row) for any case where there is no immediate prior
date. So for instance the oldest record in the table will not be in your list.

By the way, if you can do it with DLookup on a form, you should be able to
transfer that same logic into the query. You could post your DLookup code and
someone may be able to suggest how you can use that to get the desired results.
 
R

RWhittet

Dear Tom,

Here is a list of the Column names in my table. I have indicated those
columns that involve calculation where I have run into trouble with a star.

Table - Meter Usage
ID # - Primary Key
Date
Day
Employee Name
LT 24
LT 18
LT 16
CW 20
LT Mariana
LTCW 42
LT 8
North Carter - *
Comments
12 Inch RW - *
Turnout #1
North Recycle - *
Filter 14 - *
Filter 15 - *
Filter 16 - *
Filter 17 - *
Filter 18 - *
Filter 19 - *
Filter 20 - *
Filter 21 - *
Filter 22 - *
Filter 23 - *
14 Inch BW - *
South Recycle - *
South Recycle Pond Switch
South Recycle Pond
North Recycle Pond Switch
North Recycle Pond
Demand High
Demand Low AM
CB-2 Minimum Level
CB-3 Minimum Level
3-4 Flowrate
5-8 Flowrate

Thanks again for your assistance.
Richard





Tom Ellison said:
Dear Richard:

Well, Richard, I'll tell you what I do know.

I do know that I've tried various approaches to solving many database
problems. From some successes and failures, I've come to the conclusion
that the rules about how databases should be constructed are extremely
valuable. And these rules say not to store any derived values in tables.
The biggest reason for that is as follows: If you have a derived value, and
any of the stored values that are components of that value are changed, then
the derived value must immediately change as well.

I have actually written the code that will make a derived value follow any
database changes. It is about 5-10 times as much work as doing it
correctly, and it tends to be unreliable. It is too easy to forget one of
the things that might change and make the derived value incorrect.

For example, when you do this, how will you handle the case that a user
deletes the row containing the previous day's reading? How will you handle
it if the user then re-enters that row, but with a different value?

I'm telling you, it's a complex mess handling all these eventualities, if
you write the system incorrectly. However, if you simply derive all the
derived values at the moment you need them, then you won't have this
problem.

Everything in my 23 year's experience writing database software screams that
this is a really bad approach.

The kind of query you need is something I write several times a week, and
have done so hundreds of times. In my own project, this would not take me
15 minutes. I say that not to brag (there are many who post answers here
who have similar experience and capability) but to encourage you to learn
the best skills and to apply them properly. Very soon you'll see that this
becomes easy to handle, and that this is definitely the best way to handle
the situation.

As I see it, you're at a turning point in how you will develop as a database
programmer. If you listen to good advise, and put it into practice, you'll
be vastly better off.

Perhaps others who are experienced and read this will drop in and lend a
vote to what I'm telling you, so you'll see what I say is quite true, and
important. Because what I'm advising you is not my personal preference, but
a very common experience of virtually all who have advanced professionally
in this field.

If you'll expose for me the name of your table and the names of your
columns, and perhaps a bit of sample data, I'll write the query to do this.
I've done so dozens of times per year for 5 or 6 years now in this
newsgroup, and have used this as a tool to teach how this is done to dozens
of others, and with quite good success (I'm guessing more than 95%). You'll
probably be glad you did!

Tom Ellison


RWhittet said:
Dear Tom,

After talking about this I am wondering if there isn't a better approach
to
this. Lets say that I created an extra field in my table for each meter
reading, and used my calculated controls on the form to set the values of
these fields. I have played around with the set value macro before but I
haven't gotten it to work. If this is possible I think would rather go
this
route. The meters we use are pretty sophisticated, they are connected to
the
SCADA system, and we also have operators who record the readings daily.
Give
this some thought and let me know what you think and if you have any
experience with the set value macro I would appreciate that too.

Thanks,
Richard

Tom Ellison said:
Dear Richard:

Something about this makes me vary leary. So, the meter is never out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each will react
differently if a reading is missing for any reason. But I'll go ahead
anyway.

I will use an INNER JOIN between two copies of the table. JOIN it ON the
column that identifies each meter. Filter it with so one table has the
reading date equal to Forms![Meter Usage]!Date and the other to the same
date minus 1. That's at least a starting point.

I don't know the names of your table and columns. Without that I cannot
be
more specific.

Any meter for which the two readings are not both present will be omitted
from these results. It doesn't matter what kind of failure may have
produced the missing data.

Frankly, I would have thought to prorate between the reading whenever
there
is a missing reading. That is, if the meter read 13 on the first of the
month, and 22 on the fourth, then the consumption on the second, or the
third, or the fourth would each be 3 units.

Before pushing such an idea, I'd use queries to investigate where there
is
any history of a meter reading being missing. A simple aggregate of
COUNT(*) for each meter, and a COUNT(*) of every DISTINCT Date value in
the
table would tell me if there are missing readings, and how common they
are.

Those who instruct us to perform tasks like this often mistake just how
reliable their data is. I wouldn't ever argue such a point except where
it
is historically demonstrable. Once you can prove the necessity for a
cautious approach, then management can be made ready to listen.

I hope you won't think I'm being intrusive. This is really the voice of
reason and experience.

Tom Ellison


Thanks for the quick responses. There will never be a day when the
meters
are not read. The only case of an unread meter would be if that
pipeline
was
taken offline for repairs. And, this has happened. The ultimate goal
is
to
create a montly sum of the total amount of water through each meter to
be
used for billing, budgeting, predictions, etc. But, my boss created a
spreadsheet years ago that has been used ever since, so I am trying to
duplicate it, in a sense. It is important that these calculations be
accurate. The user pulling the report will select the beginning and
ending
date. The report itself is designed as a monthly report.

This is the code I have used in my form to show the previous meter
reading.

=DLookUp("[South Recycle]","[Meter Usage]","[Date] = Forms![Meter
Usage]![Date]-1")

Richard Whittet

:

Dear Richard:

Before helping prepare a way to query this, I want to check certain
facts.

You say, "These meters are read everyday" Does that mean it is never
the
case that a day goes by in which no meters are read (a holiday for
example)?
Does it mean that it is never the case that a meter is skipped?

If a day is skipped, like a holiday, then are you going to give
results
for
a 2 day period instead? If a meter is skipped, will you skip
reporting
that
meter for 2 days (the day in which it has the current reading, then
the
day
in which it has the previous reading).

Will the user pulling this report select the Day 1 date? Will you
then
report only those meter that were read on the chosen date AND on the
previous day?

Realistically, real world data has holes in it. I'm trying to get our
thinking together on whether such holes will EVER happen, and what you
want
to do in that case.

In order to do what you want, you need to use two copies of the table
in
the
same query. One feature of doing this is to alias them, so you can
reference them separately.

I need some detailed, precise information on the questions I asked
before
I
can begin to craft any solution. OK?

I'm going to suggest one possible solution to the problem. Let's say
you
have a control on a form with the more recent date in it. We could
then
build a query that filters to that date and to the immediately
preceeding
calendar date. Any meter that does not have BOTH readings would be
excluded
from the results. That's a simple, but perhaps not most desirable way
to
handle it.

Tom Ellison


I have run into a problem in my query. I am trying to run
calculations
on
water meters. I have been able to calculate the information I need
on
my
forms, by using DLookup, but it's a bit more tricky to do in the
query.
These meters are read everyday, and the calculations needed are also
daily
as
they convert the value into million gallons per day. The
calculation
is
as
follows;
(Day 2 meter reading - Day 1 meter reading)/1000

All of the readings are stored in the same table, so the biggest
problem
is
referencing the value from the previous record. I have also been
able
to
create the calculations in my reports, but I'm unable to use a
monthly
average or sum on a calculated field in a report. Any solutions or
suggestions would be greatly appreciated!

Richard Whittet
 
R

RWhittet

Dear Tom,
I see that I forgot to give you some data. So I am reposting it, sorry.

Table - Meter Usage
ID # - Primary Key - 1719
Date - 8/17/05
Day - 230
Employee Name - Richard Whittet
LT 24 - 0.49
LT 18 - 1.154
LT 16 - 2.592
CW 20 - 1.477
LT Mariana - 0.244
LTCW 42 - 11.396
LT 8 - 0.195
North Carter - * 499246
Comments
12 Inch RW - * 18635057
Turnout #1 - 0.98
North Recycle - * 488734
Filter 14 - * 137059
Filter 15 - * 122433
Filter 16 - * 3282807
Filter 17 - * 2755124
Filter 18 - * 2740611
Filter 19 - * 1275411
Filter 20 - * 1028674
Filter 21 - * 1136286
Filter 22 - * 1222160
Filter 23 - * 1072176
14 Inch BW - * 7540
South Recycle - * 1318149
South Recycle Pond Switch - yes
South Recycle Pond - 1
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.450
Demand Low AM - 5.550
CB-2 Minimum Level - 3.50
CB-3 Minimum Level - 4.21
3-4 Flowrate - 2.10
5-8 Flowrate - 4.56

Table - Meter Usage
ID # - Primary Key - 1720
Date - 8/18/05
Day - 231
Employee Name - Richard Whittet
LT 24 - 0.53
LT 18 - 1.235
LT 16 - 2.844
CW 20 - 1.427
LT Mariana - 0.315
LTCW 42 - 11.926
LT 8 - 0.213
North Carter - * 500049
Comments
12 Inch RW - * 18639524
Turnout #1 - 1.915
North Recycle - * 492855
Filter 14 - * 138449
Filter 15 - * 123823
Filter 16 - * 3284193
Filter 17 - * 2756494
Filter 18 - * 2741978
Filter 19 - * 1276836
Filter 20 - * 1030078
Filter 21 - * 1137684
Filter 22 - * 1223561
Filter 23 - * 1073563
14 Inch BW - * 7829
South Recycle - * 1319259
South Recycle Pond Switch - no
South Recycle Pond - 3
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.689
Demand Low AM - 4.689
CB-2 Minimum Level - 3.75
CB-3 Minimum Level - 4.15
3-4 Flowrate - 2.05
5-8 Flowrate - 4.50
Thanks again for your assistance.
Richard





Tom Ellison said:
Dear Richard:

Well, Richard, I'll tell you what I do know.

I do know that I've tried various approaches to solving many database
problems. From some successes and failures, I've come to the conclusion
that the rules about how databases should be constructed are extremely
valuable. And these rules say not to store any derived values in tables.
The biggest reason for that is as follows: If you have a derived value, and
any of the stored values that are components of that value are changed, then
the derived value must immediately change as well.

I have actually written the code that will make a derived value follow any
database changes. It is about 5-10 times as much work as doing it
correctly, and it tends to be unreliable. It is too easy to forget one of
the things that might change and make the derived value incorrect.

For example, when you do this, how will you handle the case that a user
deletes the row containing the previous day's reading? How will you handle
it if the user then re-enters that row, but with a different value?

I'm telling you, it's a complex mess handling all these eventualities, if
you write the system incorrectly. However, if you simply derive all the
derived values at the moment you need them, then you won't have this
problem.

Everything in my 23 year's experience writing database software screams that
this is a really bad approach.

The kind of query you need is something I write several times a week, and
have done so hundreds of times. In my own project, this would not take me
15 minutes. I say that not to brag (there are many who post answers here
who have similar experience and capability) but to encourage you to learn
the best skills and to apply them properly. Very soon you'll see that this
becomes easy to handle, and that this is definitely the best way to handle
the situation.

As I see it, you're at a turning point in how you will develop as a database
programmer. If you listen to good advise, and put it into practice, you'll
be vastly better off.

Perhaps others who are experienced and read this will drop in and lend a
vote to what I'm telling you, so you'll see what I say is quite true, and
important. Because what I'm advising you is not my personal preference, but
a very common experience of virtually all who have advanced professionally
in this field.

If you'll expose for me the name of your table and the names of your
columns, and perhaps a bit of sample data, I'll write the query to do this.
I've done so dozens of times per year for 5 or 6 years now in this
newsgroup, and have used this as a tool to teach how this is done to dozens
of others, and with quite good success (I'm guessing more than 95%). You'll
probably be glad you did!

Tom Ellison


RWhittet said:
Dear Tom,

After talking about this I am wondering if there isn't a better approach
to
this. Lets say that I created an extra field in my table for each meter
reading, and used my calculated controls on the form to set the values of
these fields. I have played around with the set value macro before but I
haven't gotten it to work. If this is possible I think would rather go
this
route. The meters we use are pretty sophisticated, they are connected to
the
SCADA system, and we also have operators who record the readings daily.
Give
this some thought and let me know what you think and if you have any
experience with the set value macro I would appreciate that too.

Thanks,
Richard

:

Dear Richard:

Something about this makes me vary leary. So, the meter is never out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each will react
differently if a reading is missing for any reason. But I'll go ahead
anyway.

I will use an INNER JOIN between two copies of the table. JOIN it ON the
column that identifies each meter. Filter it with so one table has the
reading date equal to Forms![Meter Usage]!Date and the other to the same
date minus 1. That's at least a starting point.

I don't know the names of your table and columns. Without that I cannot
be
more specific.

Any meter for which the two readings are not both present will be omitted
from these results. It doesn't matter what kind of failure may have
produced the missing data.

Frankly, I would have thought to prorate between the reading whenever
there
is a missing reading. That is, if the meter read 13 on the first of the
month, and 22 on the fourth, then the consumption on the second, or the
third, or the fourth would each be 3 units.

Before pushing such an idea, I'd use queries to investigate where there
is
any history of a meter reading being missing. A simple aggregate of
COUNT(*) for each meter, and a COUNT(*) of every DISTINCT Date value in
the
table would tell me if there are missing readings, and how common they
are.

Those who instruct us to perform tasks like this often mistake just how
reliable their data is. I wouldn't ever argue such a point except where
it
is historically demonstrable. Once you can prove the necessity for a
cautious approach, then management can be made ready to listen.

I hope you won't think I'm being intrusive. This is really the voice of
reason and experience.

Tom Ellison


Thanks for the quick responses. There will never be a day when the
meters
are not read. The only case of an unread meter would be if that
pipeline
was
taken offline for repairs. And, this has happened. The ultimate goal
is
to
create a montly sum of the total amount of water through each meter to
be
used for billing, budgeting, predictions, etc. But, my boss created a
spreadsheet years ago that has been used ever since, so I am trying to
duplicate it, in a sense. It is important that these calculations be
accurate. The user pulling the report will select the beginning and
ending
date. The report itself is designed as a monthly report.

This is the code I have used in my form to show the previous meter
reading.

=DLookUp("[South Recycle]","[Meter Usage]","[Date] = Forms![Meter
Usage]![Date]-1")

Richard Whittet

:

Dear Richard:

Before helping prepare a way to query this, I want to check certain
facts.

You say, "These meters are read everyday" Does that mean it is never
the
case that a day goes by in which no meters are read (a holiday for
example)?
Does it mean that it is never the case that a meter is skipped?

If a day is skipped, like a holiday, then are you going to give
results
for
a 2 day period instead? If a meter is skipped, will you skip
reporting
that
meter for 2 days (the day in which it has the current reading, then
the
day
in which it has the previous reading).

Will the user pulling this report select the Day 1 date? Will you
then
report only those meter that were read on the chosen date AND on the
previous day?

Realistically, real world data has holes in it. I'm trying to get our
thinking together on whether such holes will EVER happen, and what you
want
to do in that case.

In order to do what you want, you need to use two copies of the table
in
the
same query. One feature of doing this is to alias them, so you can
reference them separately.

I need some detailed, precise information on the questions I asked
before
I
can begin to craft any solution. OK?

I'm going to suggest one possible solution to the problem. Let's say
you
have a control on a form with the more recent date in it. We could
then
build a query that filters to that date and to the immediately
preceeding
calendar date. Any meter that does not have BOTH readings would be
excluded
from the results. That's a simple, but perhaps not most desirable way
to
handle it.

Tom Ellison


I have run into a problem in my query. I am trying to run
calculations
on
water meters. I have been able to calculate the information I need
on
my
forms, by using DLookup, but it's a bit more tricky to do in the
query.
These meters are read everyday, and the calculations needed are also
daily
as
they convert the value into million gallons per day. The
calculation
is
as
follows;
(Day 2 meter reading - Day 1 meter reading)/1000

All of the readings are stored in the same table, so the biggest
problem
is
referencing the value from the previous record. I have also been
able
to
create the calculations in my reports, but I'm unable to use a
monthly
average or sum on a calculated field in a report. Any solutions or
suggestions would be greatly appreciated!
 
T

Tom Ellison

Please be patient. I'll be back in about 15-16 hours.

Tom Ellison


RWhittet said:
Dear Tom,

I see that I forgot to give you some data. So I am reposting it, sorry.

Table - Meter Usage
ID # - Primary Key - 1719
Date - 8/17/05
Day - 230
Employee Name - Richard Whittet
LT 24 - 0.49
LT 18 - 1.154
LT 16 - 2.592
CW 20 - 1.477
LT Mariana - 0.244
LTCW 42 - 11.396
LT 8 - 0.195
North Carter - * 499246
Comments
12 Inch RW - * 18635057
Turnout #1 - 0.98
North Recycle - * 488734
Filter 14 - * 137059
Filter 15 - * 122433
Filter 16 - * 3282807
Filter 17 - * 2755124
Filter 18 - * 2740611
Filter 19 - * 1275411
Filter 20 - * 1028674
Filter 21 - * 1136286
Filter 22 - * 1222160
Filter 23 - * 1072176
14 Inch BW - * 7540
South Recycle - * 1318149
South Recycle Pond Switch - yes
South Recycle Pond - 1
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.450
Demand Low AM - 5.550
CB-2 Minimum Level - 3.50
CB-3 Minimum Level - 4.21
3-4 Flowrate - 2.10
5-8 Flowrate - 4.56

Table - Meter Usage
ID # - Primary Key - 1720
Date - 8/18/05
Day - 231
Employee Name - Richard Whittet
LT 24 - 0.53
LT 18 - 1.235
LT 16 - 2.844
CW 20 - 1.427
LT Mariana - 0.315
LTCW 42 - 11.926
LT 8 - 0.213
North Carter - * 500049
Comments
12 Inch RW - * 18639524
Turnout #1 - 1.915
North Recycle - * 492855
Filter 14 - * 138449
Filter 15 - * 123823
Filter 16 - * 3284193
Filter 17 - * 2756494
Filter 18 - * 2741978
Filter 19 - * 1276836
Filter 20 - * 1030078
Filter 21 - * 1137684
Filter 22 - * 1223561
Filter 23 - * 1073563
14 Inch BW - * 7829
South Recycle - * 1319259
South Recycle Pond Switch - no
South Recycle Pond - 3
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.689
Demand Low AM - 4.689
CB-2 Minimum Level - 3.75
CB-3 Minimum Level - 4.15
3-4 Flowrate - 2.05
5-8 Flowrate - 4.50
Thanks again for your assistance.
Richard





Tom Ellison said:
Dear Richard:

Well, Richard, I'll tell you what I do know.

I do know that I've tried various approaches to solving many database
problems. From some successes and failures, I've come to the
conclusion
that the rules about how databases should be constructed are extremely
valuable. And these rules say not to store any derived values in
tables.
The biggest reason for that is as follows: If you have a derived
value, and
any of the stored values that are components of that value are changed,
then
the derived value must immediately change as well.

I have actually written the code that will make a derived value follow
any
database changes. It is about 5-10 times as much work as doing it
correctly, and it tends to be unreliable. It is too easy to forget one
of
the things that might change and make the derived value incorrect.

For example, when you do this, how will you handle the case that a user
deletes the row containing the previous day's reading? How will you
handle
it if the user then re-enters that row, but with a different value?

I'm telling you, it's a complex mess handling all these eventualities,
if
you write the system incorrectly. However, if you simply derive all
the
derived values at the moment you need them, then you won't have this
problem.

Everything in my 23 year's experience writing database software screams
that
this is a really bad approach.

The kind of query you need is something I write several times a week,
and
have done so hundreds of times. In my own project, this would not take
me
15 minutes. I say that not to brag (there are many who post answers
here
who have similar experience and capability) but to encourage you to
learn
the best skills and to apply them properly. Very soon you'll see that
this
becomes easy to handle, and that this is definitely the best way to
handle
the situation.

As I see it, you're at a turning point in how you will develop as a
database
programmer. If you listen to good advise, and put it into practice,
you'll
be vastly better off.

Perhaps others who are experienced and read this will drop in and lend
a
vote to what I'm telling you, so you'll see what I say is quite true,
and
important. Because what I'm advising you is not my personal
preference, but
a very common experience of virtually all who have advanced
professionally
in this field.

If you'll expose for me the name of your table and the names of your
columns, and perhaps a bit of sample data, I'll write the query to do
this.
I've done so dozens of times per year for 5 or 6 years now in this
newsgroup, and have used this as a tool to teach how this is done to
dozens
of others, and with quite good success (I'm guessing more than 95%).
You'll
probably be glad you did!

Tom Ellison


Dear Tom,

After talking about this I am wondering if there isn't a better
approach
to
this. Lets say that I created an extra field in my table for each
meter
reading, and used my calculated controls on the form to set the
values of
these fields. I have played around with the set value macro before
but I
haven't gotten it to work. If this is possible I think would rather
go
this
route. The meters we use are pretty sophisticated, they are
connected to
the
SCADA system, and we also have operators who record the readings
daily.
Give
this some thought and let me know what you think and if you have any
experience with the set value macro I would appreciate that too.

Thanks,
Richard

:

Dear Richard:

Something about this makes me vary leary. So, the meter is never
out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each will
react
differently if a reading is missing for any reason. But I'll go
ahead
anyway.

I will use an INNER JOIN between two copies of the table. JOIN it
ON the
column that identifies each meter. Filter it with so one table has
the
reading date equal to Forms![Meter Usage]!Date and the other to the
same
date minus 1. That's at least a starting point.

I don't know the names of your table and columns. Without that I
cannot
be
more specific.

Any meter for which the two readings are not both present will be
omitted
from these results. It doesn't matter what kind of failure may have
produced the missing data.

Frankly, I would have thought to prorate between the reading
whenever
there
is a missing reading. That is, if the meter read 13 on the first of
the
month, and 22 on the fourth, then the consumption on the second, or
the
third, or the fourth would each be 3 units.

Before pushing such an idea, I'd use queries to investigate where
there
is
any history of a meter reading being missing. A simple aggregate of
COUNT(*) for each meter, and a COUNT(*) of every DISTINCT Date value
in
the
table would tell me if there are missing readings, and how common
they
are.

Those who instruct us to perform tasks like this often mistake just
how
reliable their data is. I wouldn't ever argue such a point except
where
it
is historically demonstrable. Once you can prove the necessity for
a
cautious approach, then management can be made ready to listen.

I hope you won't think I'm being intrusive. This is really the
voice of
reason and experience.

Tom Ellison


Thanks for the quick responses. There will never be a day when
the
meters
are not read. The only case of an unread meter would be if that
pipeline
was
taken offline for repairs. And, this has happened. The ultimate
goal
is
to
create a montly sum of the total amount of water through each
meter to
be
used for billing, budgeting, predictions, etc. But, my boss
created a
spreadsheet years ago that has been used ever since, so I am
trying to
duplicate it, in a sense. It is important that these calculations
be
accurate. The user pulling the report will select the beginning
and
ending
date. The report itself is designed as a monthly report.

This is the code I have used in my form to show the previous meter
reading.

=DLookUp("[South Recycle]","[Meter Usage]","[Date] = Forms![Meter
Usage]![Date]-1")

Richard Whittet

:

Dear Richard:

Before helping prepare a way to query this, I want to check
certain
facts.

You say, "These meters are read everyday" Does that mean it is
never
the
case that a day goes by in which no meters are read (a holiday
for
example)?
Does it mean that it is never the case that a meter is skipped?

If a day is skipped, like a holiday, then are you going to give
results
for
a 2 day period instead? If a meter is skipped, will you skip
reporting
that
meter for 2 days (the day in which it has the current reading,
then
the
day
in which it has the previous reading).

Will the user pulling this report select the Day 1 date? Will
you
then
report only those meter that were read on the chosen date AND on
the
previous day?

Realistically, real world data has holes in it. I'm trying to
get our
thinking together on whether such holes will EVER happen, and
what you
want
to do in that case.

In order to do what you want, you need to use two copies of the
table
in
the
same query. One feature of doing this is to alias them, so you
can
reference them separately.

I need some detailed, precise information on the questions I
asked
before
I
can begin to craft any solution. OK?

I'm going to suggest one possible solution to the problem. Let's
say
you
have a control on a form with the more recent date in it. We
could
then
build a query that filters to that date and to the immediately
preceeding
calendar date. Any meter that does not have BOTH readings would
be
excluded
from the results. That's a simple, but perhaps not most
desirable way
to
handle it.

Tom Ellison


I have run into a problem in my query. I am trying to run
calculations
on
water meters. I have been able to calculate the information I
need
on
my
forms, by using DLookup, but it's a bit more tricky to do in
the
query.
These meters are read everyday, and the calculations needed are
also
daily
as
they convert the value into million gallons per day. The
calculation
is
as
follows;
(Day 2 meter reading - Day 1 meter reading)/1000

All of the readings are stored in the same table, so the
biggest
problem
is
referencing the value from the previous record. I have also
been
able
to
create the calculations in my reports, but I'm unable to use a
monthly
average or sum on a calculated field in a report. Any
solutions or
suggestions would be greatly appreciated!
 
T

Tom Ellison

Dear John:

Thanks for the kind words.

I've known John as a fellow MVP (which we are not at the moment) and met him
in Seattle in 2004 at the MVP Summit. He, like all the MVPs I've met, is
very good at what he does and generous with his good advise. To hear from
him like this is gratifying.

Hope to see you at one of the MVP confabs again, John! Betsy sends her
greeting, too!

Tom Ellison


John Spencer said:
Well, you are getting much more comprehensive advice from Tom Ellison. If
you
can, use his advice.

The DLookup function expects strings for its arguments, so

Expr1: DLookUp("[South Recycle]","[Meter Usage]", "[Day]=#"&
DateDiff("d",-1,[Day]) &"#")

The third argument is basically a WHERE clause without "WHERE" at the
beginning
of the clause. It should end up being a string that looks like
"[Day]=#11/12/2005#"

Where 11/12/2005 is one less than the value of Day in the current record.

Like I said work with Tom Ellison - he will help you develop a robust
solution
that will take into account the missing data.
Is there a way to manipulate this expression to where it will work in the
query? I have been trying different things but it always returns the
same
days reading. I think the problem lies in the criteria of the argument.
Also, I'm not good with the SQL language so if you could retype it using
my
field and table names that would be great.

Expr1: DLookUp([South Recycle],"Meter Usage",[Day]-1)

John Spencer said:
If you have one reading for every day then this is fairly simple. If
you have
multiple readings or days get skipped then this gets to be a bit more
complex.

Simplest case - one reading EVERY day. (Substitute your field and
table names)

SELECT A.MeterID, A.ReadingDate, (A.Reading - B.Reading)/1000
FROM YourTable as A INNER JOIN YourTable As B
ON A.ReadingDate = B.ReadingDate -1
AND R.MeterID = B.MeterID

This will return NO record (row) for any case where there is no
immediate prior
date. So for instance the oldest record in the table will not be in
your list.

By the way, if you can do it with DLookup on a form, you should be able
to
transfer that same logic into the query. You could post your DLookup
code and
someone may be able to suggest how you can use that to get the desired
results.


RWhittet wrote:

I have run into a problem in my query. I am trying to run
calculations on
water meters. I have been able to calculate the information I need
on my
forms, by using DLookup, but it's a bit more tricky to do in the
query.
These meters are read everyday, and the calculations needed are also
daily as
they convert the value into million gallons per day. The calculation
is as
follows;
(Day 2 meter reading - Day 1 meter reading)/1000

All of the readings are stored in the same table, so the biggest
problem is
referencing the value from the previous record. I have also been
able to
create the calculations in my reports, but I'm unable to use a
monthly
average or sum on a calculated field in a report. Any solutions or
suggestions would be greatly appreciated!

Richard Whittet
 
T

Tom Ellison

Dear Richard:

Looking at the two records you provided, the first question is this: On
which column(s) is the relationship between the rows determined? How can I
tell that these two rows are for the same meter? Is each row the reading
for one meter on one day?

Tom Ellison

RWhittet said:
Dear Tom,

I see that I forgot to give you some data. So I am reposting it, sorry.

Table - Meter Usage
ID # - Primary Key - 1719
Date - 8/17/05
Day - 230
Employee Name - Richard Whittet
LT 24 - 0.49
LT 18 - 1.154
LT 16 - 2.592
CW 20 - 1.477
LT Mariana - 0.244
LTCW 42 - 11.396
LT 8 - 0.195
North Carter - * 499246
Comments
12 Inch RW - * 18635057
Turnout #1 - 0.98
North Recycle - * 488734
Filter 14 - * 137059
Filter 15 - * 122433
Filter 16 - * 3282807
Filter 17 - * 2755124
Filter 18 - * 2740611
Filter 19 - * 1275411
Filter 20 - * 1028674
Filter 21 - * 1136286
Filter 22 - * 1222160
Filter 23 - * 1072176
14 Inch BW - * 7540
South Recycle - * 1318149
South Recycle Pond Switch - yes
South Recycle Pond - 1
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.450
Demand Low AM - 5.550
CB-2 Minimum Level - 3.50
CB-3 Minimum Level - 4.21
3-4 Flowrate - 2.10
5-8 Flowrate - 4.56

Table - Meter Usage
ID # - Primary Key - 1720
Date - 8/18/05
Day - 231
Employee Name - Richard Whittet
LT 24 - 0.53
LT 18 - 1.235
LT 16 - 2.844
CW 20 - 1.427
LT Mariana - 0.315
LTCW 42 - 11.926
LT 8 - 0.213
North Carter - * 500049
Comments
12 Inch RW - * 18639524
Turnout #1 - 1.915
North Recycle - * 492855
Filter 14 - * 138449
Filter 15 - * 123823
Filter 16 - * 3284193
Filter 17 - * 2756494
Filter 18 - * 2741978
Filter 19 - * 1276836
Filter 20 - * 1030078
Filter 21 - * 1137684
Filter 22 - * 1223561
Filter 23 - * 1073563
14 Inch BW - * 7829
South Recycle - * 1319259
South Recycle Pond Switch - no
South Recycle Pond - 3
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.689
Demand Low AM - 4.689
CB-2 Minimum Level - 3.75
CB-3 Minimum Level - 4.15
3-4 Flowrate - 2.05
5-8 Flowrate - 4.50
Thanks again for your assistance.
Richard





Tom Ellison said:
Dear Richard:

Well, Richard, I'll tell you what I do know.

I do know that I've tried various approaches to solving many database
problems. From some successes and failures, I've come to the
conclusion
that the rules about how databases should be constructed are extremely
valuable. And these rules say not to store any derived values in
tables.
The biggest reason for that is as follows: If you have a derived
value, and
any of the stored values that are components of that value are changed,
then
the derived value must immediately change as well.

I have actually written the code that will make a derived value follow
any
database changes. It is about 5-10 times as much work as doing it
correctly, and it tends to be unreliable. It is too easy to forget one
of
the things that might change and make the derived value incorrect.

For example, when you do this, how will you handle the case that a user
deletes the row containing the previous day's reading? How will you
handle
it if the user then re-enters that row, but with a different value?

I'm telling you, it's a complex mess handling all these eventualities,
if
you write the system incorrectly. However, if you simply derive all
the
derived values at the moment you need them, then you won't have this
problem.

Everything in my 23 year's experience writing database software screams
that
this is a really bad approach.

The kind of query you need is something I write several times a week,
and
have done so hundreds of times. In my own project, this would not take
me
15 minutes. I say that not to brag (there are many who post answers
here
who have similar experience and capability) but to encourage you to
learn
the best skills and to apply them properly. Very soon you'll see that
this
becomes easy to handle, and that this is definitely the best way to
handle
the situation.

As I see it, you're at a turning point in how you will develop as a
database
programmer. If you listen to good advise, and put it into practice,
you'll
be vastly better off.

Perhaps others who are experienced and read this will drop in and lend
a
vote to what I'm telling you, so you'll see what I say is quite true,
and
important. Because what I'm advising you is not my personal
preference, but
a very common experience of virtually all who have advanced
professionally
in this field.

If you'll expose for me the name of your table and the names of your
columns, and perhaps a bit of sample data, I'll write the query to do
this.
I've done so dozens of times per year for 5 or 6 years now in this
newsgroup, and have used this as a tool to teach how this is done to
dozens
of others, and with quite good success (I'm guessing more than 95%).
You'll
probably be glad you did!

Tom Ellison


Dear Tom,

After talking about this I am wondering if there isn't a better
approach
to
this. Lets say that I created an extra field in my table for each
meter
reading, and used my calculated controls on the form to set the
values of
these fields. I have played around with the set value macro before
but I
haven't gotten it to work. If this is possible I think would rather
go
this
route. The meters we use are pretty sophisticated, they are
connected to
the
SCADA system, and we also have operators who record the readings
daily.
Give
this some thought and let me know what you think and if you have any
experience with the set value macro I would appreciate that too.

Thanks,
Richard

:

Dear Richard:

Something about this makes me vary leary. So, the meter is never
out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each will
react
differently if a reading is missing for any reason. But I'll go
ahead
anyway.

I will use an INNER JOIN between two copies of the table. JOIN it
ON the
column that identifies each meter. Filter it with so one table has
the
reading date equal to Forms![Meter Usage]!Date and the other to the
same
date minus 1. That's at least a starting point.

I don't know the names of your table and columns. Without that I
cannot
be
more specific.

Any meter for which the two readings are not both present will be
omitted
from these results. It doesn't matter what kind of failure may have
produced the missing data.

Frankly, I would have thought to prorate between the reading
whenever
there
is a missing reading. That is, if the meter read 13 on the first of
the
month, and 22 on the fourth, then the consumption on the second, or
the
third, or the fourth would each be 3 units.

Before pushing such an idea, I'd use queries to investigate where
there
is
any history of a meter reading being missing. A simple aggregate of
COUNT(*) for each meter, and a COUNT(*) of every DISTINCT Date value
in
the
table would tell me if there are missing readings, and how common
they
are.

Those who instruct us to perform tasks like this often mistake just
how
reliable their data is. I wouldn't ever argue such a point except
where
it
is historically demonstrable. Once you can prove the necessity for
a
cautious approach, then management can be made ready to listen.

I hope you won't think I'm being intrusive. This is really the
voice of
reason and experience.

Tom Ellison


Thanks for the quick responses. There will never be a day when
the
meters
are not read. The only case of an unread meter would be if that
pipeline
was
taken offline for repairs. And, this has happened. The ultimate
goal
is
to
create a montly sum of the total amount of water through each
meter to
be
used for billing, budgeting, predictions, etc. But, my boss
created a
spreadsheet years ago that has been used ever since, so I am
trying to
duplicate it, in a sense. It is important that these calculations
be
accurate. The user pulling the report will select the beginning
and
ending
date. The report itself is designed as a monthly report.

This is the code I have used in my form to show the previous meter
reading.

=DLookUp("[South Recycle]","[Meter Usage]","[Date] = Forms![Meter
Usage]![Date]-1")

Richard Whittet

:

Dear Richard:

Before helping prepare a way to query this, I want to check
certain
facts.

You say, "These meters are read everyday" Does that mean it is
never
the
case that a day goes by in which no meters are read (a holiday
for
example)?
Does it mean that it is never the case that a meter is skipped?

If a day is skipped, like a holiday, then are you going to give
results
for
a 2 day period instead? If a meter is skipped, will you skip
reporting
that
meter for 2 days (the day in which it has the current reading,
then
the
day
in which it has the previous reading).

Will the user pulling this report select the Day 1 date? Will
you
then
report only those meter that were read on the chosen date AND on
the
previous day?

Realistically, real world data has holes in it. I'm trying to
get our
thinking together on whether such holes will EVER happen, and
what you
want
to do in that case.

In order to do what you want, you need to use two copies of the
table
in
the
same query. One feature of doing this is to alias them, so you
can
reference them separately.

I need some detailed, precise information on the questions I
asked
before
I
can begin to craft any solution. OK?

I'm going to suggest one possible solution to the problem. Let's
say
you
have a control on a form with the more recent date in it. We
could
then
build a query that filters to that date and to the immediately
preceeding
calendar date. Any meter that does not have BOTH readings would
be
excluded
from the results. That's a simple, but perhaps not most
desirable way
to
handle it.

Tom Ellison


I have run into a problem in my query. I am trying to run
calculations
on
water meters. I have been able to calculate the information I
need
on
my
forms, by using DLookup, but it's a bit more tricky to do in
the
query.
These meters are read everyday, and the calculations needed are
also
daily
as
they convert the value into million gallons per day. The
calculation
is
as
follows;
(Day 2 meter reading - Day 1 meter reading)/1000

All of the readings are stored in the same table, so the
biggest
problem
is
referencing the value from the previous record. I have also
been
able
to
create the calculations in my reports, but I'm unable to use a
monthly
average or sum on a calculated field in a report. Any
solutions or
suggestions would be greatly appreciated!
 
R

RWhittet

Dear Tom,

The relationship between the rows is determined by the date field. I
apologize if the way I pasted the information is confusing. If you would
prefer, I could figure out an easier way to get this information to you.
Each row is the reading for one meter on one day. If you look to the far
left column of the message, you will see the field names, such as:LT 24, LT
18, LT 16 and Filter 14-23. Each one of those represents a meter and the
number that follows them is the meter reading for that day.

Richard

Tom Ellison said:
Dear Richard:

Looking at the two records you provided, the first question is this: On
which column(s) is the relationship between the rows determined? How can I
tell that these two rows are for the same meter? Is each row the reading
for one meter on one day?

Tom Ellison

RWhittet said:
Dear Tom,

I see that I forgot to give you some data. So I am reposting it, sorry.

Table - Meter Usage
ID # - Primary Key - 1719
Date - 8/17/05
Day - 230
Employee Name - Richard Whittet
LT 24 - 0.49
LT 18 - 1.154
LT 16 - 2.592
CW 20 - 1.477
LT Mariana - 0.244
LTCW 42 - 11.396
LT 8 - 0.195
North Carter - * 499246
Comments
12 Inch RW - * 18635057
Turnout #1 - 0.98
North Recycle - * 488734
Filter 14 - * 137059
Filter 15 - * 122433
Filter 16 - * 3282807
Filter 17 - * 2755124
Filter 18 - * 2740611
Filter 19 - * 1275411
Filter 20 - * 1028674
Filter 21 - * 1136286
Filter 22 - * 1222160
Filter 23 - * 1072176
14 Inch BW - * 7540
South Recycle - * 1318149
South Recycle Pond Switch - yes
South Recycle Pond - 1
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.450
Demand Low AM - 5.550
CB-2 Minimum Level - 3.50
CB-3 Minimum Level - 4.21
3-4 Flowrate - 2.10
5-8 Flowrate - 4.56

Table - Meter Usage
ID # - Primary Key - 1720
Date - 8/18/05
Day - 231
Employee Name - Richard Whittet
LT 24 - 0.53
LT 18 - 1.235
LT 16 - 2.844
CW 20 - 1.427
LT Mariana - 0.315
LTCW 42 - 11.926
LT 8 - 0.213
North Carter - * 500049
Comments
12 Inch RW - * 18639524
Turnout #1 - 1.915
North Recycle - * 492855
Filter 14 - * 138449
Filter 15 - * 123823
Filter 16 - * 3284193
Filter 17 - * 2756494
Filter 18 - * 2741978
Filter 19 - * 1276836
Filter 20 - * 1030078
Filter 21 - * 1137684
Filter 22 - * 1223561
Filter 23 - * 1073563
14 Inch BW - * 7829
South Recycle - * 1319259
South Recycle Pond Switch - no
South Recycle Pond - 3
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.689
Demand Low AM - 4.689
CB-2 Minimum Level - 3.75
CB-3 Minimum Level - 4.15
3-4 Flowrate - 2.05
5-8 Flowrate - 4.50
Thanks again for your assistance.
Richard





:

Dear Richard:

Well, Richard, I'll tell you what I do know.

I do know that I've tried various approaches to solving many database
problems. From some successes and failures, I've come to the
conclusion
that the rules about how databases should be constructed are extremely
valuable. And these rules say not to store any derived values in
tables.
The biggest reason for that is as follows: If you have a derived
value, and
any of the stored values that are components of that value are changed,
then
the derived value must immediately change as well.

I have actually written the code that will make a derived value follow
any
database changes. It is about 5-10 times as much work as doing it
correctly, and it tends to be unreliable. It is too easy to forget one
of
the things that might change and make the derived value incorrect.

For example, when you do this, how will you handle the case that a user
deletes the row containing the previous day's reading? How will you
handle
it if the user then re-enters that row, but with a different value?

I'm telling you, it's a complex mess handling all these eventualities,
if
you write the system incorrectly. However, if you simply derive all
the
derived values at the moment you need them, then you won't have this
problem.

Everything in my 23 year's experience writing database software screams
that
this is a really bad approach.

The kind of query you need is something I write several times a week,
and
have done so hundreds of times. In my own project, this would not take
me
15 minutes. I say that not to brag (there are many who post answers
here
who have similar experience and capability) but to encourage you to
learn
the best skills and to apply them properly. Very soon you'll see that
this
becomes easy to handle, and that this is definitely the best way to
handle
the situation.

As I see it, you're at a turning point in how you will develop as a
database
programmer. If you listen to good advise, and put it into practice,
you'll
be vastly better off.

Perhaps others who are experienced and read this will drop in and lend
a
vote to what I'm telling you, so you'll see what I say is quite true,
and
important. Because what I'm advising you is not my personal
preference, but
a very common experience of virtually all who have advanced
professionally
in this field.

If you'll expose for me the name of your table and the names of your
columns, and perhaps a bit of sample data, I'll write the query to do
this.
I've done so dozens of times per year for 5 or 6 years now in this
newsgroup, and have used this as a tool to teach how this is done to
dozens
of others, and with quite good success (I'm guessing more than 95%).
You'll
probably be glad you did!

Tom Ellison


Dear Tom,

After talking about this I am wondering if there isn't a better
approach
to
this. Lets say that I created an extra field in my table for each
meter
reading, and used my calculated controls on the form to set the
values of
these fields. I have played around with the set value macro before
but I
haven't gotten it to work. If this is possible I think would rather
go
this
route. The meters we use are pretty sophisticated, they are
connected to
the
SCADA system, and we also have operators who record the readings
daily.
Give
this some thought and let me know what you think and if you have any
experience with the set value macro I would appreciate that too.

Thanks,
Richard

:

Dear Richard:

Something about this makes me vary leary. So, the meter is never
out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each will
react
differently if a reading is missing for any reason. But I'll go
ahead
anyway.

I will use an INNER JOIN between two copies of the table. JOIN it
ON the
column that identifies each meter. Filter it with so one table has
the
reading date equal to Forms![Meter Usage]!Date and the other to the
same
date minus 1. That's at least a starting point.

I don't know the names of your table and columns. Without that I
cannot
be
more specific.

Any meter for which the two readings are not both present will be
omitted
from these results. It doesn't matter what kind of failure may have
produced the missing data.

Frankly, I would have thought to prorate between the reading
whenever
there
is a missing reading. That is, if the meter read 13 on the first of
the
month, and 22 on the fourth, then the consumption on the second, or
the
third, or the fourth would each be 3 units.

Before pushing such an idea, I'd use queries to investigate where
there
is
any history of a meter reading being missing. A simple aggregate of
COUNT(*) for each meter, and a COUNT(*) of every DISTINCT Date value
in
the
table would tell me if there are missing readings, and how common
they
are.

Those who instruct us to perform tasks like this often mistake just
how
reliable their data is. I wouldn't ever argue such a point except
where
it
is historically demonstrable. Once you can prove the necessity for
a
cautious approach, then management can be made ready to listen.

I hope you won't think I'm being intrusive. This is really the
voice of
reason and experience.

Tom Ellison


Thanks for the quick responses. There will never be a day when
the
meters
are not read. The only case of an unread meter would be if that
pipeline
was
taken offline for repairs. And, this has happened. The ultimate
goal
is
to
create a montly sum of the total amount of water through each
meter to
be
used for billing, budgeting, predictions, etc. But, my boss
created a
spreadsheet years ago that has been used ever since, so I am
trying to
 
T

Tom Ellison

Dear Richard:

Looking at your data, I had already suspected you have a large amount of
normalization problem.

To be effective, your database should have one row for each combination of
meter and date. There are excellent ways of doing this.

Typically, you would have a table of all the meters involved. Each meter
would be uniquely named.

You could temprorarily fix this by creating a UNION query that creates this
appearance.

For the time being, then, all you comparisons are between a single record
for all of today's readings and another record for all of yesterday's
readings. The foundational query for this would be:

SELECT *
FROM [Meter Usage] MU0, [Meter Usage] MU1
WHERE MU0.Date = #11/26/05#
AND MU1.Date = #11/25/05#

This puts all the columns of 2 of your records together. You can then
simply add a difference calculation between them.

This could become complicated by the 255 column limitation for any table or
query. Probably you wouldn't have much problem for now, but if you have
more and more meters then it will become more and more of a problem.

As it is, if you needed to add a meter you'd need to add a new column to the
table for its data and then change all the reports and forms working with
this. That's really the hard way of doing it.

Tom Ellison


RWhittet said:
Dear Tom,

The relationship between the rows is determined by the date field. I
apologize if the way I pasted the information is confusing. If you would
prefer, I could figure out an easier way to get this information to you.
Each row is the reading for one meter on one day. If you look to the far
left column of the message, you will see the field names, such as:LT 24,
LT
18, LT 16 and Filter 14-23. Each one of those represents a meter and the
number that follows them is the meter reading for that day.

Richard

Tom Ellison said:
Dear Richard:

Looking at the two records you provided, the first question is this: On
which column(s) is the relationship between the rows determined? How can
I
tell that these two rows are for the same meter? Is each row the reading
for one meter on one day?

Tom Ellison

RWhittet said:
Dear Tom,

I see that I forgot to give you some data. So I am reposting it,
sorry.

Table - Meter Usage
ID # - Primary Key - 1719
Date - 8/17/05
Day - 230
Employee Name - Richard Whittet
LT 24 - 0.49
LT 18 - 1.154
LT 16 - 2.592
CW 20 - 1.477
LT Mariana - 0.244
LTCW 42 - 11.396
LT 8 - 0.195
North Carter - * 499246
Comments
12 Inch RW - * 18635057
Turnout #1 - 0.98
North Recycle - * 488734
Filter 14 - * 137059
Filter 15 - * 122433
Filter 16 - * 3282807
Filter 17 - * 2755124
Filter 18 - * 2740611
Filter 19 - * 1275411
Filter 20 - * 1028674
Filter 21 - * 1136286
Filter 22 - * 1222160
Filter 23 - * 1072176
14 Inch BW - * 7540
South Recycle - * 1318149
South Recycle Pond Switch - yes
South Recycle Pond - 1
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.450
Demand Low AM - 5.550
CB-2 Minimum Level - 3.50
CB-3 Minimum Level - 4.21
3-4 Flowrate - 2.10
5-8 Flowrate - 4.56

Table - Meter Usage
ID # - Primary Key - 1720
Date - 8/18/05
Day - 231
Employee Name - Richard Whittet
LT 24 - 0.53
LT 18 - 1.235
LT 16 - 2.844
CW 20 - 1.427
LT Mariana - 0.315
LTCW 42 - 11.926
LT 8 - 0.213
North Carter - * 500049
Comments
12 Inch RW - * 18639524
Turnout #1 - 1.915
North Recycle - * 492855
Filter 14 - * 138449
Filter 15 - * 123823
Filter 16 - * 3284193
Filter 17 - * 2756494
Filter 18 - * 2741978
Filter 19 - * 1276836
Filter 20 - * 1030078
Filter 21 - * 1137684
Filter 22 - * 1223561
Filter 23 - * 1073563
14 Inch BW - * 7829
South Recycle - * 1319259
South Recycle Pond Switch - no
South Recycle Pond - 3
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.689
Demand Low AM - 4.689
CB-2 Minimum Level - 3.75
CB-3 Minimum Level - 4.15
3-4 Flowrate - 2.05
5-8 Flowrate - 4.50
Thanks again for your assistance.
Richard





:

Dear Richard:

Well, Richard, I'll tell you what I do know.

I do know that I've tried various approaches to solving many
database
problems. From some successes and failures, I've come to the
conclusion
that the rules about how databases should be constructed are
extremely
valuable. And these rules say not to store any derived values in
tables.
The biggest reason for that is as follows: If you have a derived
value, and
any of the stored values that are components of that value are
changed,
then
the derived value must immediately change as well.

I have actually written the code that will make a derived value
follow
any
database changes. It is about 5-10 times as much work as doing it
correctly, and it tends to be unreliable. It is too easy to forget
one
of
the things that might change and make the derived value incorrect.

For example, when you do this, how will you handle the case that a
user
deletes the row containing the previous day's reading? How will you
handle
it if the user then re-enters that row, but with a different value?

I'm telling you, it's a complex mess handling all these
eventualities,
if
you write the system incorrectly. However, if you simply derive all
the
derived values at the moment you need them, then you won't have this
problem.

Everything in my 23 year's experience writing database software
screams
that
this is a really bad approach.

The kind of query you need is something I write several times a
week,
and
have done so hundreds of times. In my own project, this would not
take
me
15 minutes. I say that not to brag (there are many who post answers
here
who have similar experience and capability) but to encourage you to
learn
the best skills and to apply them properly. Very soon you'll see
that
this
becomes easy to handle, and that this is definitely the best way to
handle
the situation.

As I see it, you're at a turning point in how you will develop as a
database
programmer. If you listen to good advise, and put it into practice,
you'll
be vastly better off.

Perhaps others who are experienced and read this will drop in and
lend
a
vote to what I'm telling you, so you'll see what I say is quite
true,
and
important. Because what I'm advising you is not my personal
preference, but
a very common experience of virtually all who have advanced
professionally
in this field.

If you'll expose for me the name of your table and the names of your
columns, and perhaps a bit of sample data, I'll write the query to
do
this.
I've done so dozens of times per year for 5 or 6 years now in this
newsgroup, and have used this as a tool to teach how this is done to
dozens
of others, and with quite good success (I'm guessing more than 95%).
You'll
probably be glad you did!

Tom Ellison


Dear Tom,

After talking about this I am wondering if there isn't a better
approach
to
this. Lets say that I created an extra field in my table for each
meter
reading, and used my calculated controls on the form to set the
values of
these fields. I have played around with the set value macro
before
but I
haven't gotten it to work. If this is possible I think would
rather
go
this
route. The meters we use are pretty sophisticated, they are
connected to
the
SCADA system, and we also have operators who record the readings
daily.
Give
this some thought and let me know what you think and if you have
any
experience with the set value macro I would appreciate that too.

Thanks,
Richard

:

Dear Richard:

Something about this makes me vary leary. So, the meter is never
out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each will
react
differently if a reading is missing for any reason. But I'll go
ahead
anyway.

I will use an INNER JOIN between two copies of the table. JOIN
it
ON the
column that identifies each meter. Filter it with so one table
has
the
reading date equal to Forms![Meter Usage]!Date and the other to
the
same
date minus 1. That's at least a starting point.

I don't know the names of your table and columns. Without that I
cannot
be
more specific.

Any meter for which the two readings are not both present will be
omitted
from these results. It doesn't matter what kind of failure may
have
produced the missing data.

Frankly, I would have thought to prorate between the reading
whenever
there
is a missing reading. That is, if the meter read 13 on the first
of
the
month, and 22 on the fourth, then the consumption on the second,
or
the
third, or the fourth would each be 3 units.

Before pushing such an idea, I'd use queries to investigate where
there
is
any history of a meter reading being missing. A simple aggregate
of
COUNT(*) for each meter, and a COUNT(*) of every DISTINCT Date
value
in
the
table would tell me if there are missing readings, and how common
they
are.

Those who instruct us to perform tasks like this often mistake
just
how
reliable their data is. I wouldn't ever argue such a point
except
where
it
is historically demonstrable. Once you can prove the necessity
for
a
cautious approach, then management can be made ready to listen.

I hope you won't think I'm being intrusive. This is really the
voice of
reason and experience.

Tom Ellison


Thanks for the quick responses. There will never be a day when
the
meters
are not read. The only case of an unread meter would be if
that
pipeline
was
taken offline for repairs. And, this has happened. The
ultimate
goal
is
to
create a montly sum of the total amount of water through each
meter to
be
used for billing, budgeting, predictions, etc. But, my boss
created a
spreadsheet years ago that has been used ever since, so I am
trying to
 
R

RWhittet

Dear Tom,

I'm not real sure if we are on the same page right now. I know that I have
some normalization issues in this database, particuliarly with the naming,
but I thought I had the tables set up correctly. We've been using the
database for about three years and it's done more than anyone expected it to.
I want to make sure I am understanding what you said correctly, so for
11/26/2005, I would have some 20 rows of data? The way I have understood it
is that I should have one record for all of the day's meter readings, not 20.


Tom Ellison said:
Dear Richard:

Looking at your data, I had already suspected you have a large amount of
normalization problem.

To be effective, your database should have one row for each combination of
meter and date. There are excellent ways of doing this.

Typically, you would have a table of all the meters involved. Each meter
would be uniquely named.

You could temprorarily fix this by creating a UNION query that creates this
appearance.

For the time being, then, all you comparisons are between a single record
for all of today's readings and another record for all of yesterday's
readings. The foundational query for this would be:

SELECT *
FROM [Meter Usage] MU0, [Meter Usage] MU1
WHERE MU0.Date = #11/26/05#
AND MU1.Date = #11/25/05#

This puts all the columns of 2 of your records together. You can then
simply add a difference calculation between them.

This could become complicated by the 255 column limitation for any table or
query. Probably you wouldn't have much problem for now, but if you have
more and more meters then it will become more and more of a problem.

As it is, if you needed to add a meter you'd need to add a new column to the
table for its data and then change all the reports and forms working with
this. That's really the hard way of doing it.

Tom Ellison


RWhittet said:
Dear Tom,

The relationship between the rows is determined by the date field. I
apologize if the way I pasted the information is confusing. If you would
prefer, I could figure out an easier way to get this information to you.
Each row is the reading for one meter on one day. If you look to the far
left column of the message, you will see the field names, such as:LT 24,
LT
18, LT 16 and Filter 14-23. Each one of those represents a meter and the
number that follows them is the meter reading for that day.

Richard
 
T

Tom Ellison

Dear Richard:

When it comes to being able to make an analysis like the one you mention, it
really is much better to have 20 rows for 20 meters than just on row for 20
meters.

But the real test is this. What would you have to do to add a new meter?
If the answer is that you'd have to add a new column to a table and change
all the forms and reports, then you have a severe normalization problem.

For your more immediate needs, did you try the query I proposed?

Tom Ellison


RWhittet said:
Dear Tom,

I'm not real sure if we are on the same page right now. I know that I
have
some normalization issues in this database, particuliarly with the naming,
but I thought I had the tables set up correctly. We've been using the
database for about three years and it's done more than anyone expected it
to.
I want to make sure I am understanding what you said correctly, so for
11/26/2005, I would have some 20 rows of data? The way I have understood
it
is that I should have one record for all of the day's meter readings, not
20.


Tom Ellison said:
Dear Richard:

Looking at your data, I had already suspected you have a large amount of
normalization problem.

To be effective, your database should have one row for each combination
of
meter and date. There are excellent ways of doing this.

Typically, you would have a table of all the meters involved. Each meter
would be uniquely named.

You could temprorarily fix this by creating a UNION query that creates
this
appearance.

For the time being, then, all you comparisons are between a single record
for all of today's readings and another record for all of yesterday's
readings. The foundational query for this would be:

SELECT *
FROM [Meter Usage] MU0, [Meter Usage] MU1
WHERE MU0.Date = #11/26/05#
AND MU1.Date = #11/25/05#

This puts all the columns of 2 of your records together. You can then
simply add a difference calculation between them.

This could become complicated by the 255 column limitation for any table
or
query. Probably you wouldn't have much problem for now, but if you have
more and more meters then it will become more and more of a problem.

As it is, if you needed to add a meter you'd need to add a new column to
the
table for its data and then change all the reports and forms working with
this. That's really the hard way of doing it.

Tom Ellison


RWhittet said:
Dear Tom,

The relationship between the rows is determined by the date field. I
apologize if the way I pasted the information is confusing. If you
would
prefer, I could figure out an easier way to get this information to
you.
Each row is the reading for one meter on one day. If you look to the
far
left column of the message, you will see the field names, such as:LT
24,
LT
18, LT 16 and Filter 14-23. Each one of those represents a meter and
the
number that follows them is the meter reading for that day.

Richard

:

Dear Richard:

Looking at the two records you provided, the first question is this:
On
which column(s) is the relationship between the rows determined? How
can
I
tell that these two rows are for the same meter? Is each row the
reading
for one meter on one day?

Tom Ellison

Dear Tom,

I see that I forgot to give you some data. So I am reposting it,
sorry.

Table - Meter Usage
ID # - Primary Key - 1719
Date - 8/17/05
Day - 230
Employee Name - Richard Whittet
LT 24 - 0.49
LT 18 - 1.154
LT 16 - 2.592
CW 20 - 1.477
LT Mariana - 0.244
LTCW 42 - 11.396
LT 8 - 0.195
North Carter - * 499246
Comments
12 Inch RW - * 18635057
Turnout #1 - 0.98
North Recycle - * 488734
Filter 14 - * 137059
Filter 15 - * 122433
Filter 16 - * 3282807
Filter 17 - * 2755124
Filter 18 - * 2740611
Filter 19 - * 1275411
Filter 20 - * 1028674
Filter 21 - * 1136286
Filter 22 - * 1222160
Filter 23 - * 1072176
14 Inch BW - * 7540
South Recycle - * 1318149
South Recycle Pond Switch - yes
South Recycle Pond - 1
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.450
Demand Low AM - 5.550
CB-2 Minimum Level - 3.50
CB-3 Minimum Level - 4.21
3-4 Flowrate - 2.10
5-8 Flowrate - 4.56

Table - Meter Usage
ID # - Primary Key - 1720
Date - 8/18/05
Day - 231
Employee Name - Richard Whittet
LT 24 - 0.53
LT 18 - 1.235
LT 16 - 2.844
CW 20 - 1.427
LT Mariana - 0.315
LTCW 42 - 11.926
LT 8 - 0.213
North Carter - * 500049
Comments
12 Inch RW - * 18639524
Turnout #1 - 1.915
North Recycle - * 492855
Filter 14 - * 138449
Filter 15 - * 123823
Filter 16 - * 3284193
Filter 17 - * 2756494
Filter 18 - * 2741978
Filter 19 - * 1276836
Filter 20 - * 1030078
Filter 21 - * 1137684
Filter 22 - * 1223561
Filter 23 - * 1073563
14 Inch BW - * 7829
South Recycle - * 1319259
South Recycle Pond Switch - no
South Recycle Pond - 3
North Recycle Pond Switch - no
North Recycle Pond - 1
Demand High - 8.689
Demand Low AM - 4.689
CB-2 Minimum Level - 3.75
CB-3 Minimum Level - 4.15
3-4 Flowrate - 2.05
5-8 Flowrate - 4.50
Thanks again for your assistance.
Richard





:

Dear Richard:

Well, Richard, I'll tell you what I do know.

I do know that I've tried various approaches to solving many
database
problems. From some successes and failures, I've come to the
conclusion
that the rules about how databases should be constructed are
extremely
valuable. And these rules say not to store any derived values in
tables.
The biggest reason for that is as follows: If you have a derived
value, and
any of the stored values that are components of that value are
changed,
then
the derived value must immediately change as well.

I have actually written the code that will make a derived value
follow
any
database changes. It is about 5-10 times as much work as doing
it
correctly, and it tends to be unreliable. It is too easy to
forget
one
of
the things that might change and make the derived value
incorrect.

For example, when you do this, how will you handle the case that
a
user
deletes the row containing the previous day's reading? How will
you
handle
it if the user then re-enters that row, but with a different
value?

I'm telling you, it's a complex mess handling all these
eventualities,
if
you write the system incorrectly. However, if you simply derive
all
the
derived values at the moment you need them, then you won't have
this
problem.

Everything in my 23 year's experience writing database software
screams
that
this is a really bad approach.

The kind of query you need is something I write several times a
week,
and
have done so hundreds of times. In my own project, this would
not
take
me
15 minutes. I say that not to brag (there are many who post
answers
here
who have similar experience and capability) but to encourage you
to
learn
the best skills and to apply them properly. Very soon you'll see
that
this
becomes easy to handle, and that this is definitely the best way
to
handle
the situation.

As I see it, you're at a turning point in how you will develop as
a
database
programmer. If you listen to good advise, and put it into
practice,
you'll
be vastly better off.

Perhaps others who are experienced and read this will drop in and
lend
a
vote to what I'm telling you, so you'll see what I say is quite
true,
and
important. Because what I'm advising you is not my personal
preference, but
a very common experience of virtually all who have advanced
professionally
in this field.

If you'll expose for me the name of your table and the names of
your
columns, and perhaps a bit of sample data, I'll write the query
to
do
this.
I've done so dozens of times per year for 5 or 6 years now in
this
newsgroup, and have used this as a tool to teach how this is done
to
dozens
of others, and with quite good success (I'm guessing more than
95%).
You'll
probably be glad you did!

Tom Ellison


Dear Tom,

After talking about this I am wondering if there isn't a better
approach
to
this. Lets say that I created an extra field in my table for
each
meter
reading, and used my calculated controls on the form to set the
values of
these fields. I have played around with the set value macro
before
but I
haven't gotten it to work. If this is possible I think would
rather
go
this
route. The meters we use are pretty sophisticated, they are
connected to
the
SCADA system, and we also have operators who record the
readings
daily.
Give
this some thought and let me know what you think and if you
have
any
experience with the set value macro I would appreciate that
too.

Thanks,
Richard

:

Dear Richard:

Something about this makes me vary leary. So, the meter is
never
out of
order, and the reading never fails to take place?

Still, the query can be written in different ways, and each
will
react
differently if a reading is missing for any reason. But I'll
go
ahead
anyway.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Top