Discussion:
Query Involving Sums and Two Most Recent Dates
Ken Dibble
2018-06-21 14:31:43 UTC
Permalink
Hi Folks,

I have to admit that I've never been able to figure out how to get
MAX() to work correctly in queries.

Given the following tables (simplified):

Consumers

PK
1
2
3

Status

PK ConFK Date Type
1 1 {^2018/1/15} Pending
2 1 {^2018/4/15} Approved
3 2 {^2018/6/1} Closed
4 2 {^2018/4/15} Approved
5 3 {^2017/11/22} Pending
6 3 {^2018/2/3} Approved
7 3 {^2018/3/12} Suspended
8 3 {^2018/5/11} Approved

Hours

PK ConFK Date AppHours
1 2 {^2017/7/3} 10
2 2 {^2018/3/12} 14
3 3 {^2018/4/1/} 20
4 3 {^2018/5/1} 12

Query: How many Consumers have a most recent Status of Approved, and
what is the sum of those Consumers' Approved Hours?

Answer: 2 Approved Consumers, having a total of 12 Hours.

I realize it's probably two queries: one for the sum of Consumers,
and one for the sum of Hours. However, I have been unable to figure
out how to write a simple query to get either of those two values.

I have laborious code that does things like pulling in all of the
Status records for each consumer and sorting them by date to find the
most recent one, and then doing the same for Hours records, and then
munging the data together into a final output cursor, and it works
fine and is fast enough, but it just makes me crazy every time
somebody wants a slightly different report along these lines.

It seems like there should be a way to do this more simply.

I am sure that I am missing something extremely obvious.

Thanks for any help.

Ken Dibble
www.stic-cil.org



_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Peter Cushing
2018-06-21 16:01:00 UTC
Permalink
Hi Ken,

You can get them both with 1 query.

select count(*) as nCust,sum(apphours) as nApphours from status,hours ;
   where status.pk = hours.pk and status.type = 'Approved' group by 1 ;
  into cursor curres

HTH

Peter


Peter Cushing
IT Department
WHISPERING SMITH
Post by Ken Dibble
Hi Folks,
I have to admit that I've never been able to figure out how to get
MAX() to work correctly in queries.
Consumers
PK
1
2
3
Status
PK    ConFK        Date        Type
1    1        {^2018/1/15}     Pending
2    1        {^2018/4/15}    Approved
3    2        {^2018/6/1}    Closed
4    2        {^2018/4/15}    Approved
5    3        {^2017/11/22}    Pending
6    3        {^2018/2/3}    Approved
7    3        {^2018/3/12}    Suspended
8    3        {^2018/5/11}    Approved
Hours
PK    ConFK        Date        AppHours
1    2        {^2017/7/3}    10
2    2        {^2018/3/12}    14
3    3        {^2018/4/1/}    20
4    3        {^2018/5/1}    12
Query: How many Consumers have a most recent Status of Approved, and
what is the sum of those Consumers' Approved Hours?
Answer: 2 Approved Consumers, having a total of 12 Hours.
I realize it's probably two queries: one for the sum of Consumers, and
one for the sum of Hours. However, I have been unable to figure out
how to write a simple query to get either of those two values.
I have laborious code that does things like pulling in all of the
Status records for each consumer and sorting them by date to find the
most recent one, and then doing the same for Hours records, and then
munging the data together into a final output cursor, and it works
fine and is fast enough, but it just makes me crazy every time
somebody wants a slightly different report along these lines.
It seems like there should be a way to do this more simply.
I am sure that I am missing something extremely obvious.
Thanks for any help.
Ken Dibble
www.stic-cil.org
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/dd797add-4d43-b833-d8c7-***@whisperingsmith.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for thos
Peter Cushing
2018-06-21 16:03:11 UTC
Permalink
Hi Ken,

You can get them both with 1 query. Pressed send too soon on the last
reply.

select status.pk,count(*) as nCust,sum(apphours) as nApphours ;
from status,hours ;
   where status.pk = hours.pk and status.type = 'Approved' group by 1 ;
  into cursor curres

HTH

Peter


Peter Cushing
IT Department
WHISPERING SMITH
Post by Ken Dibble
Hi Folks,
I have to admit that I've never been able to figure out how to get
MAX() to work correctly in queries.
Consumers
PK
1
2
3
Status
PK    ConFK        Date        Type
1    1        {^2018/1/15}     Pending
2    1        {^2018/4/15}    Approved
3    2        {^2018/6/1}    Closed
4    2        {^2018/4/15}    Approved
5    3        {^2017/11/22}    Pending
6    3        {^2018/2/3}    Approved
7    3        {^2018/3/12}    Suspended
8    3        {^2018/5/11}    Approved
Hours
PK    ConFK        Date        AppHours
1    2        {^2017/7/3}    10
2    2        {^2018/3/12}    14
3    3        {^2018/4/1/}    20
4    3        {^2018/5/1}    12
Query: How many Consumers have a most recent Status of Approved, and
what is the sum of those Consumers' Approved Hours?
Answer: 2 Approved Consumers, having a total of 12 Hours.
I realize it's probably two queries: one for the sum of Consumers, and
one for the sum of Hours. However, I have been unable to figure out
how to write a simple query to get either of those two values.
I have laborious code that does things like pulling in all of the
Status records for each consumer and sorting them by date to find the
most recent one, and then doing the same for Hours records, and then
munging the data together into a final output cursor, and it works
fine and is fast enough, but it just makes me crazy every time
somebody wants a slightly different report along these lines.
It seems like there should be a way to do this more simply.
I am sure that I am missing something extremely obvious.
Thanks for any help.
Ken Dibble
www.stic-cil.org
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/e4bc8a34-01cf-2f0d-d66d-***@whisperingsmith.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for th
Ted Roche
2018-06-21 16:06:57 UTC
Permalink
Post by Ken Dibble
Hi Folks,
I have to admit that I've never been able to figure out how to get MAX() to
work correctly in queries.
Consumers
PK
1
2
3
Status
PK ConFK Date Type
1 1 {^2018/1/15} Pending
2 1 {^2018/4/15} Approved
3 2 {^2018/6/1} Closed
4 2 {^2018/4/15} Approved
5 3 {^2017/11/22} Pending
6 3 {^2018/2/3} Approved
7 3 {^2018/3/12} Suspended
8 3 {^2018/5/11} Approved
Hours
PK ConFK Date AppHours
1 2 {^2017/7/3} 10
2 2 {^2018/3/12} 14
3 3 {^2018/4/1/} 20
4 3 {^2018/5/1} 12
Query: How many Consumers have a most recent Status of Approved, and what is
the sum of those Consumers' Approved Hours?
Answer: 2 Approved Consumers, having a total of 12 Hours.
Not at a machine with VFP, so I can't test this, but it looks good in
Google Mail :)

SELECT Consumer.*, Status.*, SUM(Hours.AppHours) AS TotalHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date = (SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK)
AND Status.Type = "Approved"
--
Ted Roche
Ted Roche & Associates, LLC
http://www.tedroche.com

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/CACW6n4sOg5KjDvcTX5TRU7C2A3-XuP1yms=***@mail.gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ken Dibble
2018-06-21 16:22:17 UTC
Permalink
Post by Ted Roche
SELECT Consumer.*, Status.*, SUM(Hours.AppHours) AS TotalHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date = (SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK)
AND Status.Type = "Approved"
Thank you, but I think I left out a requirement. The hours have to
come from the most recent Hours records as well.

Ken


_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ken Dibble
2018-06-21 17:06:10 UTC
Permalink
Post by Ken Dibble
Post by Ted Roche
SELECT Consumer.*, Status.*, SUM(Hours.AppHours) AS TotalHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date = (SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK)
AND Status.Type = "Approved"
Thank you, but I think I left out a requirement. The hours have to
come from the most recent Hours records as well.
Also appears to require a GROUP BY clause.

Thanks.

Ken


_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ted Roche
2018-06-21 17:18:34 UTC
Permalink
Thank you, but I think I left out a requirement. The hours have to come from
the most recent Hours records as well.
I should have realized that from your example solution. I *ASSuMEd* we
were totalling hours. My bad.

SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK GROUP BY Stat2.ConFK)
AND Status.Type = "Approved"
AND Hours.Date = Status.Date

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/CACW6n4uyNe0DmhRphsXehLffYO=C-TVSKoMZ-nA_hYgw7NZ-***@mail.gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ken Dibble
2018-06-21 17:27:07 UTC
Permalink
Post by Ted Roche
I should have realized that from your example solution. I *ASSuMEd* we
were totalling hours. My bad.
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK GROUP BY Stat2.ConFK)
AND Status.Type = "Approved"
AND Hours.Date = Status.Date
Better, but there is no guarantee that Hours.Date will equal Status.Date.

The results have to total the most recent hours records belonging to
Consumers whose most recent Status is "Approved".

And my testing indicates that a GROUP BY clause is required somewhere.

I'm wondering if this will turn out to be np-hard and my original
multi-query approach is the only way to do this.

Thanks.

Ken


_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ken Dibble
2018-06-21 17:32:53 UTC
Permalink
Er... and while still rendering a total number of Consumers whose
hours were totalled--at least via _TALLY if nothing else.
Post by Ken Dibble
Post by Ted Roche
I should have realized that from your example solution. I *ASSuMEd* we
were totalling hours. My bad.
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK GROUP BY Stat2.ConFK)
AND Status.Type = "Approved"
AND Hours.Date = Status.Date
Better, but there is no guarantee that Hours.Date will equal Status.Date.
And my testing indicates that a GROUP BY clause is required somewhere.
I'm wondering if this will turn out to be np-hard and my original
multi-query approach is the only way to do this.
Thanks.
Ken
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ted Roche
2018-06-21 17:55:24 UTC
Permalink
Post by Ken Dibble
Better, but there is no guarantee that Hours.Date will equal Status.Date.
...
Post by Ken Dibble
I'm wondering if this will turn out to be np-hard and my original
multi-query approach is the only way to do this.
No, it's just a little quirky due to your design choices. Typically, I
would have a "current status" value in the Consumer record that's an
FK into the Status history table.

A common problem with data modeling is determining if your system is a
reflection of the current version of the system, or the history of the
states of the system, or a mix of both.
Post by Ken Dibble
The results have to total the most recent hours records belonging to
Consumers whose most recent Status is "Approved".
I think your description of the hours result is a little ambiguous,
and since I've guessed wrong twice, I'll stop now. ;)

Are you SUM'ming Hours records for the Consumer SINCE their status
became approved, or are you picking the LAST Hours record for
Consumers currently Approved? Either is easy. Ish.
Post by Ken Dibble
And my testing indicates that a GROUP BY clause is required somewhere.
It's in there, with the sub-select with the MAX
Post by Ken Dibble
Post by Ted Roche
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK GROUP BY Stat2.ConFK)
AND Status.Type = "Approved"
AND Hours.Date = Status.Date
--
Ted Roche
Ted Roche & Associates, LLC
http://www.tedroche.com

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/CACW6n4tDYxxTAURB6hXM7z5Xtf_LcTv=5-***@mail.gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ken Dibble
2018-06-21 18:22:37 UTC
Permalink
Post by Ted Roche
No, it's just a little quirky due to your design choices. Typically, I
would have a "current status" value in the Consumer record that's an
FK into the Status history table.
A common problem with data modeling is determining if your system is a
reflection of the current version of the system, or the history of the
states of the system, or a mix of both.
Interesting. I've always just followed the principle that if a parent
can own more than one value for a particular item, you put that item
in a child record, and keep the child records in a separate table and
JOIN it as needed. I thought that was a requirement for
normalization. It would seem to engender less upkeep than creating a
need to update something in the parent record whenever you change
something in the child record. Also, if a need develops for the
parent to own more than one of something else that was not part of
the original design, something which would require yet another child
table, I would then also have to modify the parent table to add a
"most recent" field for that. Modifying existing tables containing
data seems more risky than simply adding empty tables--especially
when I have to do it in a completely automated way for remote
locations whose hardware I don't trust.
Post by Ted Roche
Post by Ken Dibble
The results have to total the most recent hours records belonging to
Consumers whose most recent Status is "Approved".
I think your description of the hours result is a little ambiguous,
and since I've guessed wrong twice, I'll stop now. ;)
Are you SUM'ming Hours records for the Consumer SINCE their status
became approved, or are you picking the LAST Hours record for
Consumers currently Approved? Either is easy. Ish.
I need a total of the Hours stored to all of the LAST hours records
that are owned by Consumers whose LAST status record contains
"Approved" in the "type" field. Bear in mind that a Consumer may not
own any records in the Hours table at all.
Post by Ted Roche
Post by Ken Dibble
And my testing indicates that a GROUP BY clause is required somewhere.
It's in there, with the sub-select with the MAX
Yes it is. Sorry that I missed it.

Thanks for all of your help.

Ken



_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ted Roche
2018-06-21 19:23:02 UTC
Permalink
Interesting. I've always just followed the principle that if a parent can
own more than one value for a particular item, you put that item in a child
record, and keep the child records in a separate table and JOIN it as
needed.
So, can a Consumer be both Approved and Pending?

By your logic, if a Company Name on a company record could change
(when Acme Widgets is taken over by Apex Amalgamated) that should be
in a child table, with a date range for when each name is effective.

If the status is always only one value at that point in time, but may
change over time, you might store the CURRENT STATUS in the Consumer
table, and an history (or Audit Trail) of updates to that status in a
Status Audit Trail table.

It's an issue of modeling the dimension of time in your database
schema. Typically, the current status is what you want to check when
you query the tables: how much stuff is in stock, how many projects
are pending, etc. all come with the implicit requirement of "at this
time." But other reports would question "how did this inventory vary
over time" which would trace history/audit-trail records.
I thought that was a requirement for normalization. It would seem to
engender less upkeep than creating a need to update something in the parent
record whenever you change something in the child record.
Only if the two things mean the same thing. The Consumer record stores
the current state. The Status Audit table stores the history of state
changes. They may have similar names, but are in fact different pieces
of information.

Consumer: Approved is the current status of the process
Status table: Approved, {^2018-6-21) is the date the process got that status.
Also, if a need
develops for the parent to own more than one of something else that was not
part of the original design, something which would require yet another child
table,
That's a "yeah, but what if" hypothetical. By that rationale, all data
schemas are out of date, and we should just use document databases.
Let's skip that slippery slope.

If changes happen, the data schema might have to change. That's why
the database manufacturers gave us that capability.
I would then also have to modify the parent table to add a "most
recent" field for that. Modifying existing tables containing data seems more
risky than simply adding empty tables--especially when I have to do it in a
completely automated way for remote locations whose hardware I don't trust.
Solving hardware problems with bad software is rarely a win. Backup,
migrate, validate, rollback or commit.
Post by Ted Roche
Post by Ken Dibble
The results have to total the most recent hours records belonging to
Consumers whose most recent Status is "Approved".
I think your description of the hours result is a little ambiguous,
and since I've guessed wrong twice, I'll stop now. ;)
Are you SUM'ming Hours records for the Consumer SINCE their status
became approved, or are you picking the LAST Hours record for
Consumers currently Approved? Either is easy. Ish.
I need a total of the Hours stored to all of the LAST hours records that are
owned by Consumers whose LAST status record contains "Approved" in the
"type" field.
Bear in mind that a Consumer may not own any records in the
Hours table at all.
New info.

SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
LEFT OUTER JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK GROUP BY Stat2.ConFK)
AND Status.Type = "Approved"
AND Hours.Date = (SELECT MAX(Hours2.Date) FROM Hours Hours2 WHERE
Hours2.ConFK = Consumer.ConPK GROUP BY Hours.PK)

Where Hours.AppHours come out as NULL, you'll want to substitute zero
to get Approved Consumers who have no Hours record posted.
--
Ted Roche
Ted Roche & Associates, LLC
http://www.tedroche.com

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/CACW6n4tmw40VU7SJ5dspadntF82Bqedq8R-***@mail.gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ken Dibble
2018-06-22 14:45:14 UTC
Permalink
Post by Ted Roche
Interesting. I've always just followed the principle that if a parent can
own more than one value for a particular item, you put that item in a child
record, and keep the child records in a separate table and JOIN it as
needed.
So, can a Consumer be both Approved and Pending?
By your logic, if a Company Name on a company record could change
(when Acme Widgets is taken over by Apex Amalgamated) that should be
in a child table, with a date range for when each name is effective.
If the status is always only one value at that point in time, but may
change over time, you might store the CURRENT STATUS in the Consumer
table, and an history (or Audit Trail) of updates to that status in a
Status Audit Trail table.
It's an issue of modeling the dimension of time in your database
schema. Typically, the current status is what you want to check when
you query the tables: how much stuff is in stock, how many projects
are pending, etc. all come with the implicit requirement of "at this
time." But other reports would question "how did this inventory vary
over time" which would trace history/audit-trail records.
This is probably the best way for me to think about this.

It may or may not be needless to say that it's waaaay too late to
change the design of the database and related code in such a
fundamental way--if I concluded that, in my specific case, it would
be the best way to go. I've given you one example of a problem that
occurs in several different modules of the system, each with its own
set of parent records and child tables, many of which have
"expiration" or "supercession" (is that a word?) dates. This isn't
sales with invoices and orders; it's a quasi-medical case
management/service/process tracking and documentation system. Users
need to look at the "historical" information frequently.

I did actually write a generic method for my reporting system a few
years ago that can accept a few parms and take the long way around
(multiple queries and sorting tricks) to produce these kinds of
results regardless of the tables being processed. It works for a
reasonably large subset of these problems, but this particular case,
a report asking for a couple of totals rather than a list of names
and related items, is sufficiently different and unusual in my case
to make me think about doing something different. Unfortunately, I
can't do something THAT different.
Post by Ted Roche
I thought that was a requirement for normalization. It would seem to
engender less upkeep than creating a need to update something in the parent
record whenever you change something in the child record.
Only if the two things mean the same thing. The Consumer record stores
the current state. The Status Audit table stores the history of state
changes. They may have similar names, but are in fact different pieces
of information.
Consumer: Approved is the current status of the process
Status table: Approved, {^2018-6-21) is the date the process got that status.
I think I have to respectfully disagree here. Perhaps it's only the
(undiagnosed) Aspergerishness in me. But I am an entirely self-taught
developer who does not really understand set theory very well. A
program that I produced in the early 1990s to perform some of the
tasks the current system handles had a single, very large table that
stored everything. At the time it was required to report whether a
specific service had been delivered to a specific consumer at least
once per quarter. So the table had one row per consumer and a field
for each service and each quarter: S1Q1, S2Q1... S1Q3... etc.

There was at that time no need to maintain a historical record of
services; at the end of each reporting year the service fields were
purged and we started again. Neverthess, I think everyone would say
this was a terrible design.

I don't think that adding a different effective date to a piece of
data that is otherwise identical to other pieces of data makes it a
"different thing" in normalization terms. I can see that in some
cases it would be more convenient to do so. But if instead of two or
three dated items per parent, what if I had fifteen or twenty?

My system provides a utility function to superusers; they can add new
Status options without requiring me to do any programming. And they
frequently do this. Following your suggestion, I would have to do
programming to modify the parent tables every time they did that. (I
can't automate it; I have to boot everybody out of the system to
modify tables that are constantly in use.)

You might say, "Oh. That's new information." However, If I had given
you 3000 words explaining the full complexity of the system in
advance, you would have responded "tl;dr".

I am always struggling to understand the principles behind these
things, but every time I think I've found one somebody comes along
and tells me, no, that's not it. It makes everything, in the end,
seem terribly ad hoc, and that makes it really difficult for me to
apply what I've learned to new situations.

Still, I deeply appreciate the time you've given to me and the
opportunity to learn something that you always provide.
Post by Ted Roche
If changes happen, the data schema might have to change. That's why
the database manufacturers gave us that capability.
And this can be severely screwed up, causing major damage. While
wearing one of my other hats on this job, for the last three weeks I
have been struggling with a company that provides Medicaid billing
software. A user had a question. The company refused to answer the
question until we installed the latest version. We always approach
this with trepidation, because there are always problems. But I
installed the update. The process went without a hitch and all of the
tests on the data afterwards checked out.

However, as the users began working with the system, they began
encountering major slowdowns, and if more than one was in the system
at the same time, it would crash with "deadlock" errors.

Company support suggested that we had hit the wall on the SQL Server
Express we were using and suggested we purchase the full version of
SQL Server. So I spent $1300 to do that, and installed it. Even
though the amount of data that was being processed before the
update--at least in terms of what we had entered--had not changed
after the update.

The updating process required, as it always does, a lengthy
"conversion" of the database (it took nearly an hour on a Windows
2012 server VM with 24 GB of RAM and 4 very beefy Xeon processors).
There's a detailed list of the changes made in each version. They
added a bunch of new fields and tables, among other things, and
probably moved things around in the manner that you suggest is
necessary and routine.

As a result, the size of the database was significantly bloated--and
if I had to guess, they did not thoroughly test the updates with
datasets the size of ours (which is, apparently, unusually large for
them), to ensure that everything was optimized. The conversion
process may even have corrupted the data. Since then we have been
arguing with them daily, and they keep trying to tell me that my
hardware capacity (which exceeds their minimum specifications by a
huge margin), or the out-of-the-box SQL Server configuration (which I
do not know how to change and for which I would have to hire a
consultant), had suddenly become too weak for the system between the
time they took a version of the database that was working fine, and
converted it--without us adding any data--to a much larger database
that does not work fine. We are now facing a serious cash flow
problem because we can't get enough billing out on a daily basis.
Post by Ted Roche
I need a total of the Hours stored to all of the LAST hours
records that are
owned by Consumers whose LAST status record contains "Approved" in the
"type" field.
Bear in mind that a Consumer may not own any records in the
Hours table at all.
New info.
Welcome to my world. The "customer" for this particular module is
extremely inarticulate. I always go through multiple iterations with
her before I finally get to giving her what she really wants. I've
been working with her for a long time; she is not getting any better
at telling me at the beginning exactly what I should do. Here is the
request from her that initiated this process, verbatim:

"Can you create a report so I can determine how many people are
currently approved for services and the total amount of units the
people are approved for?"

Having learned through experience that talking to her about it would
not produce significantly greater clarity, I just went ahead and
started developing some code that would appear to answer her
question. I really wanted to just run an ad hoc query in the
development environment without constructing an interface or
integrating it into the system so I could show her what answer my
interpretation of the question would provide. I knew she would then
say, "No.. it's not really that..." and we would be off to the races.

As for the code: I will test yours and Frank's solutions and respond
later today.

Thank you very much!!

Ken



_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ken Dibble
2018-06-22 16:21:46 UTC
Permalink
Post by Ted Roche
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
LEFT OUTER JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK GROUP BY Stat2.ConFK)
AND Status.Type = "Approved"
AND Hours.Date = (SELECT MAX(Hours2.Date) FROM Hours Hours2 WHERE
Hours2.ConFK = Consumer.ConPK GROUP BY Hours.PK)
I actually can't get this to run without errors. Interpolating, I
Post by Ted Roche
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
LEFT OUTER JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK AND Status.Type = "Approved" GROUP BY
Stat2.ConFK)
AND Hours.Date = (SELECT MAX(Hours2.Date) FROM Hours Hours2 WHERE
Hours2.ConFK = Consumer.ConPK GROUP BY Hours.PK)
However, I get "Function missing )" on the last subquery on this
this, and neither intellisense nor I can find any unmatched parens.

Also, the first subquery is grouping on the Status table FK, while
the second subquery groups on the Hours table PK. I think they should
both group on the same key, but I don't understand which one that should be.

Thanks.

Ken


_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Frank Cazabon
2018-06-22 17:11:06 UTC
Permalink
Did you run it as part of the first set of code that I gave you?

It runs here with no errors in VFP9 with the latest hot fix and SPs. ;)

What error is it giving you? Maybe a line split somewhere due to the
email formatting?

This is the full code:

CREATE CURSOR Consumers;
(ConPK int)

INSERT INTO consumers (ConPK ) VALUES (1)
INSERT INTO consumers (ConPK ) VALUES (2)
INSERT INTO consumers (ConPK ) VALUES  (3)
*!*    1
*!*    2
*!*    3

*!*    Status
CREATE CURSOR Status;
(StatPK int,;
ConFK Int,;
Date date,;
Type c(10))

INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(1,1,{^2018/1/15},"Pending")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(2,1,{^2018/4/15},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(3,2,{^2018/6/1},"Closed")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(4,2,{^2018/4/15},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(5,3,{^2017/11/22},"Pending")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(6,3,{^2018/2/3},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(7,3,{^2018/3/12},"Suspended")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(8,3,{^2018/5/11},"Approved")

CREATE CURSOR Hours;
(HourPK int,;
conFK int,;
Date d,;
Apphours int)

*!*    PK,ConFK,,Date,,AppHours
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(1,2,{^2017/7/3},10)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(2,2,{^2018/3/12},14)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(3,3,{^2018/4/1},20)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(4,3,{^2018/5/1},12 )



SELECT Status.ConFK, LastHours.AppHours;
    FROM Status ;
    INNER JOIN (SELECT ConFK, MAX(Date) AS MaxDate;
        FROM Status;
        GROUP BY ConFK) M ON Status.ConFK = M.ConFK AND Status.Date =
M.MaxDate ;
    AND Type = "Approved";
LEFT JOIN (SELECT Hours.ConFK, Hours.AppHours;
            FROM Hours;
            INNER JOIN (SELECT ConFK, MAX(date) AS MaxHoursDate;
                            FROM Hours;
                            GROUP BY ConFK) MH ;
                        ON Hours.ConFK = MH.ConFK AND Hours.Date =
MH.MaxHoursDate ) LastHours ;
            ON STatus.ConFK = LastHours.ConFK

Frank.

Frank Cazabon
Post by Ken Dibble
Post by Ted Roche
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
LEFT OUTER JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK GROUP BY Stat2.ConFK)
AND Status.Type = "Approved"
AND Hours.Date = (SELECT MAX(Hours2.Date) FROM Hours Hours2 WHERE
Hours2.ConFK = Consumer.ConPK GROUP BY Hours.PK)
I actually can't get this to run without errors. Interpolating, I
Post by Ted Roche
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
LEFT OUTER JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK AND Status.Type = "Approved" GROUP BY
Stat2.ConFK)
AND Hours.Date = (SELECT MAX(Hours2.Date) FROM Hours Hours2 WHERE
Hours2.ConFK = Consumer.ConPK GROUP BY Hours.PK)
However, I get "Function missing )" on the last subquery on this this,
and neither intellisense nor I can find any unmatched parens.
Also, the first subquery is grouping on the Status table FK, while the
second subquery groups on the Hours table PK. I think they should both
group on the same key, but I don't understand which one that should be.
Thanks.
Ken
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/26171e1f-9942-d0ab-010e-***@gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for
Frank Cazabon
2018-06-22 17:19:41 UTC
Permalink
Ken,

Sorry, I hadn't realised you were responding to Ted's code.

Frank.

Frank Cazabon
Post by Frank Cazabon
Did you run it as part of the first set of code that I gave you?
It runs here with no errors in VFP9 with the latest hot fix and SPs. ;)
What error is it giving you? Maybe a line split somewhere due to the
email formatting?
CREATE CURSOR Consumers;
(ConPK int)
INSERT INTO consumers (ConPK ) VALUES (1)
INSERT INTO consumers (ConPK ) VALUES (2)
INSERT INTO consumers (ConPK ) VALUES  (3)
*!*    1
*!*    2
*!*    3
*!*    Status
CREATE CURSOR Status;
(StatPK int,;
ConFK Int,;
Date date,;
Type c(10))
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(1,1,{^2018/1/15},"Pending")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(2,1,{^2018/4/15},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(3,2,{^2018/6/1},"Closed")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(4,2,{^2018/4/15},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(5,3,{^2017/11/22},"Pending")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(6,3,{^2018/2/3},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(7,3,{^2018/3/12},"Suspended")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(8,3,{^2018/5/11},"Approved")
CREATE CURSOR Hours;
(HourPK int,;
conFK int,;
Date d,;
Apphours int)
*!*    PK,ConFK,,Date,,AppHours
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(1,2,{^2017/7/3},10)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(2,2,{^2018/3/12},14)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(3,3,{^2018/4/1},20)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(4,3,{^2018/5/1},12 )
SELECT Status.ConFK, LastHours.AppHours;
    FROM Status ;
    INNER JOIN (SELECT ConFK, MAX(Date) AS MaxDate;
        FROM Status;
        GROUP BY ConFK) M ON Status.ConFK = M.ConFK AND Status.Date =
M.MaxDate ;
    AND Type = "Approved";
LEFT JOIN (SELECT Hours.ConFK, Hours.AppHours;
            FROM Hours;
            INNER JOIN (SELECT ConFK, MAX(date) AS MaxHoursDate;
                            FROM Hours;
                            GROUP BY ConFK) MH ;
                        ON Hours.ConFK = MH.ConFK AND Hours.Date =
MH.MaxHoursDate ) LastHours ;
            ON STatus.ConFK = LastHours.ConFK
Frank.
Frank Cazabon
Post by Ken Dibble
Post by Ted Roche
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
LEFT OUTER JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK GROUP BY Stat2.ConFK)
AND Status.Type = "Approved"
AND Hours.Date = (SELECT MAX(Hours2.Date) FROM Hours Hours2 WHERE
Hours2.ConFK = Consumer.ConPK GROUP BY Hours.PK)
I actually can't get this to run without errors. Interpolating, I
Post by Ted Roche
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
LEFT OUTER JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK AND Status.Type = "Approved" GROUP BY
Stat2.ConFK)
AND Hours.Date = (SELECT MAX(Hours2.Date) FROM Hours Hours2 WHERE
Hours2.ConFK = Consumer.ConPK GROUP BY Hours.PK)
However, I get "Function missing )" on the last subquery on this
this, and neither intellisense nor I can find any unmatched parens.
Also, the first subquery is grouping on the Status table FK, while
the second subquery groups on the Hours table PK. I think they should
both group on the same key, but I don't understand which one that
should be.
Thanks.
Ken
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/dc50fdae-a444-b805-3a7e-***@gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too s
Ken Dibble
2018-06-22 17:20:10 UTC
Permalink
Frank,

You're responding here to my response to Ted's code, not yours.

Your code runs fine, and I responded to that separately.

Ken
Content-Transfer-Encoding: base64Did you run it
as part of the first set of code that I gave you?
It runs here with no errors in VFP9 with the latest hot fix and SPs. ;)
What error is it giving you? Maybe a line split
somewhere due to the email formatting?
CREATE CURSOR Consumers;
(ConPK int)
INSERT INTO consumers (ConPK ) VALUES (1)
INSERT INTO consumers (ConPK ) VALUES (2)
INSERT INTO consumers (ConPK ) VALUES (3)
*!* 1
*!* 2
*!* 3
*!* Status
CREATE CURSOR Status;
(StatPK int,;
ConFK Int,;
Date date,;
Type c(10))
INSERT INTO Status (StatPK , ConFK, Date, Type)
VALUES (1,1,{^2018/1/15},"Pending")
INSERT INTO Status (StatPK , ConFK, Date, Type)
VALUES (2,1,{^2018/4/15},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type)
VALUES (3,2,{^2018/6/1},"Closed")
INSERT INTO Status (StatPK , ConFK, Date, Type)
VALUES (4,2,{^2018/4/15},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type)
VALUES (5,3,{^2017/11/22},"Pending")
INSERT INTO Status (StatPK , ConFK, Date, Type)
VALUES (6,3,{^2018/2/3},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type)
VALUES (7,3,{^2018/3/12},"Suspended")
INSERT INTO Status (StatPK , ConFK, Date, Type)
VALUES (8,3,{^2018/5/11},"Approved")
CREATE CURSOR Hours;
(HourPK int,;
conFK int,;
Date d,;
Apphours int)
*!* PK,ConFK,,Date,,AppHours
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES (1,2,{^2017/7/3},10)
INSERT INTO Hours (HourPK , ConFK, Date,
AppHours) VALUES (2,2,{^2018/3/12},14)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES (3,3,{^2018/4/1},20)
INSERT INTO Hours (HourPK , ConFK, Date,
AppHours) VALUES (4,3,{^2018/5/1},12 )
SELECT Status.ConFK, LastHours.AppHours;
FROM Status ;
INNER JOIN (SELECT ConFK, MAX(Date) AS MaxDate;
FROM Status;
GROUP BY ConFK) M ON Status.ConFK =
M.ConFK AND Status.Date = M.MaxDate ;
AND Type = "Approved";
LEFT JOIN (SELECT Hours.ConFK, Hours.AppHours;
FROM Hours;
INNER JOIN (SELECT ConFK, MAX(date) AS MaxHoursDate;
FROM Hours;
GROUP BY ConFK) MH ;
ON Hours.ConFK =
MH.ConFK AND Hours.Date = MH.MaxHoursDate ) LastHours ;
 ON STatus.ConFK = LastHours.ConFK
Frank.
Frank Cazabon
ˆÑSPÕÛۜÝ[Y\‹Š‹Ý]\ˊ‹Ý\œË\Ý\œ€ FROM Consumer
Post by Ted Roche
JOIN Status on Consumer.ConPK=Status.ConFK
Q•ÕUTˆ“ÒSˆÝ\œÈۈÛۜÝ[Y\‹Û۔ÏRÝ\œËÛۑ€K
ˆÒT‘HÝ]\ˑ]HB‚…4TÄT5BԂ…7FC"äFFR’e$ôÒStatus Stat2 WHERE
Ý]‹Ûۑ’ÈHÛۜÝ[Y\‹Û۔ÈԓÕTBY Stat2.ConFK)
S‘Ý]\˕\HH\›Ý™Y‚ˆS‘Àurs.Date = (SELECT
MAX(Hours2.Date) FROM Hours Hours2 WHERE
Post by Ted Roche
Hours2.ConFK = Consumer.ConPK GROUP BY Hours.PK)
I actually can't get this to run without
‚4TÄT5B6öç7VÖW"â , Status.*, Hours.AppHours
Post by Ted Roche
FROM Consumer
LEFT OUTER JOIN Hours on Consumer.ConPK=Hours.ConFK
ÒT‘HÝ]\ˑ]HBˆ(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Post by Ted Roche
Stat2.ConFK = Consumer.ConPK AND Status.Type = "Approved" GROUP BY
ˆÝ]‹Ûۑ’ÊBˆS‘Ý\œË‘]HH
ÑSPÕPV
Ý\€s2.Date) FROM Hours Hours2 WHERE
Post by Ted Roche
Hours2.ConFK = Consumer.ConPK GROUP BY Hours.PK)
However, I get "Function missing )" on the last subquery on this this,
[™™Z]her intellisense nor I can find any unmatched parens.
Also, the first subquery is grouping on the Status table FK, while the
second subquery groups on the Hours table PK. I
think they should both group on the same key,
but I don't understand which one that should be.
ˆÙ[‚‚‚­Ù^Ù\ÜÚ]™H][Ý[™È™[[ݙYžH[excessive quoting removed by server]
_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ted Roche
2018-06-21 17:56:12 UTC
Permalink
Yeah, that's worth testing, and GMail doesn't tell me that :) I'm
guessing _TALLY should be the number, but you can always check
RECCOUNT() of the query result.
Er... and while still rendering a total number of Consumers whose hours were
totalled--at least via _TALLY if nothing else.
Post by Ken Dibble
Post by Ted Roche
I should have realized that from your example solution. I *ASSuMEd* we
were totalling hours. My bad.
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK GROUP BY Stat2.ConFK)
AND Status.Type = "Approved"
AND Hours.Date = Status.Date
Better, but there is no guarantee that Hours.Date will equal Status.Date.
And my testing indicates that a GROUP BY clause is required somewhere.
I'm wondering if this will turn out to be np-hard and my original
multi-query approach is the only way to do this.
Thanks.
Ken
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/CACW6n4sKBuzF4Bmwt2BAqv=TafUWxRhKCv5ikYz970J2rKoC+***@mail.gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Richard Kaye
2018-06-21 19:03:40 UTC
Permalink
Personally I avoid _TALLY since so many commands & functions in VFP will change it.

--

rk

-----Original Message-----
From: ProfoxTech <profoxtech-***@leafe.com> On Behalf Of Ted Roche
Sent: Thursday, June 21, 2018 1:56 PM
To: ***@leafe.com
Subject: Re: Query Involving Sums and Two Most Recent Dates

Yeah, that's worth testing, and GMail doesn't tell me that :) I'm
guessing _TALLY should be the number, but you can always check
RECCOUNT() of the query result.
Er... and while still rendering a total number of Consumers whose hours were
totalled--at least via _TALLY if nothing else.
Post by Ken Dibble
Post by Ted Roche
I should have realized that from your example solution. I *ASSuMEd* we
were totalling hours. My bad.
SELECT Consumer.*, Status.*, Hours.AppHours
FROM Consumer
JOIN Status on Consumer.ConPK=Status.ConFK
JOIN Hours on Consumer.ConPK=Hours.ConFK
WHERE Status.Date =
(SELECT MAX(Stat2.Date) FROM Status Stat2 WHERE
Stat2.ConFK = Consumer.ConPK GROUP BY Stat2.ConFK)
AND Status.Type = "Approved"
AND Hours.Date = Status.Date
Better, but there is no guarantee that Hours.Date will equal Status.Date.
And my testing indicates that a GROUP BY clause is required somewhere.
I'm wondering if this will turn out to be np-hard and my original
multi-query approach is the only way to do this.
Thanks.
Ken
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/***@DM5PR10MB1244.namprd10.prod.outlook.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ken Dibble
2018-06-22 16:51:09 UTC
Permalink
Post by Richard Kaye
Personally I avoid _TALLY since so many commands & functions in VFP will change it.
I don't think there's any danger of it getting changed if I store the
contents of _TALLY to a local variable immediately after running the
query, which is what I always do.

I think RECCOUNT() moves the record pointer, which might not be
desirable in some circumstances but wouldn't make a difference in my case.

Ken Dibble
www.stic-cil.org


_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Frank Cazabon
2018-06-21 18:21:13 UTC
Permalink
What's your expected output from the data you presented?

To make it a little easier for people to try to help, here's some code
to build up the data and my attempt at what I've understood as your
requirements:

CREATE CURSOR Consumers;
(ConPK int)

INSERT INTO consumers (ConPK ) VALUES (1)
INSERT INTO consumers (ConPK ) VALUES (2)
INSERT INTO consumers (ConPK ) VALUES  (3)

CREATE CURSOR Status;
(StatPK int,;
ConFK Int,;
Date date,;
Type c(10))

INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(1,1,{^2018/1/15},"Pending")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(2,1,{^2018/4/15},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(3,2,{^2018/6/1},"Closed")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(4,2,{^2018/4/15},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(5,3,{^2017/11/22},"Pending")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(6,3,{^2018/2/3},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(7,3,{^2018/3/12},"Suspended")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(8,3,{^2018/5/11},"Approved")

CREATE CURSOR Hours;
(HourPK int,;
conFK int,;
Date d,;
Apphours int)

INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(1,2,{^2017/7/3},10)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(2,2,{^2018/3/12},14)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(3,3,{^2018/4/1},20)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(4,3,{^2018/5/1},12 )


Frank.

Frank Cazabon
Post by Ken Dibble
Hi Folks,
I have to admit that I've never been able to figure out how to get
MAX() to work correctly in queries.
Consumers
PK
1
2
3
Status
PK    ConFK        Date        Type
1    1        {^2018/1/15}     Pending
2    1        {^2018/4/15}    Approved
3    2        {^2018/6/1}    Closed
4    2        {^2018/4/15}    Approved
5    3        {^2017/11/22}    Pending
6    3        {^2018/2/3}    Approved
7    3        {^2018/3/12}    Suspended
8    3        {^2018/5/11}    Approved
Hours
PK    ConFK        Date        AppHours
1    2        {^2017/7/3}    10
2    2        {^2018/3/12}    14
3    3        {^2018/4/1/}    20
4    3        {^2018/5/1}    12
Query: How many Consumers have a most recent Status of Approved, and
what is the sum of those Consumers' Approved Hours?
Answer: 2 Approved Consumers, having a total of 12 Hours.
I realize it's probably two queries: one for the sum of Consumers, and
one for the sum of Hours. However, I have been unable to figure out
how to write a simple query to get either of those two values.
I have laborious code that does things like pulling in all of the
Status records for each consumer and sorting them by date to find the
most recent one, and then doing the same for Hours records, and then
munging the data together into a final output cursor, and it works
fine and is fast enough, but it just makes me crazy every time
somebody wants a slightly different report along these lines.
It seems like there should be a way to do this more simply.
I am sure that I am missing something extremely obvious.
Thanks for any help.
Ken Dibble
www.stic-cil.org
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/35b084fd-63d5-05e8-4e1e-***@gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see th
Frank Cazabon
2018-06-21 18:25:39 UTC
Permalink
Sorry, left off my attempt as I realised I hadn't understood the requirements properly
Post by Frank Cazabon
What's your expected output from the data you presented?
To make it a little easier for people to try to help, here's some code
to build up the data and my attempt at what I've understood as your
CREATE CURSOR Consumers;
(ConPK int)
INSERT INTO consumers (ConPK ) VALUES (1)
INSERT INTO consumers (ConPK ) VALUES (2)
INSERT INTO consumers (ConPK ) VALUES  (3)
CREATE CURSOR Status;
(StatPK int,;
ConFK Int,;
Date date,;
Type c(10))
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(1,1,{^2018/1/15},"Pending")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(2,1,{^2018/4/15},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(3,2,{^2018/6/1},"Closed")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(4,2,{^2018/4/15},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(5,3,{^2017/11/22},"Pending")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(6,3,{^2018/2/3},"Approved")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(7,3,{^2018/3/12},"Suspended")
INSERT INTO Status (StatPK , ConFK, Date, Type) VALUES
(8,3,{^2018/5/11},"Approved")
CREATE CURSOR Hours;
(HourPK int,;
conFK int,;
Date d,;
Apphours int)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(1,2,{^2017/7/3},10)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(2,2,{^2018/3/12},14)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(3,3,{^2018/4/1},20)
INSERT INTO Hours (HourPK , ConFK, Date, AppHours) VALUES
(4,3,{^2018/5/1},12 )
Frank.
Frank Cazabon
Post by Ken Dibble
Hi Folks,
I have to admit that I've never been able to figure out how to get
MAX() to work correctly in queries.
Consumers
PK
1
2
3
Status
PK    ConFK        Date        Type
1    1        {^2018/1/15}     Pending
2    1        {^2018/4/15}    Approved
3    2        {^2018/6/1}    Closed
4    2        {^2018/4/15}    Approved
5    3        {^2017/11/22}    Pending
6    3        {^2018/2/3}    Approved
7    3        {^2018/3/12}    Suspended
8    3        {^2018/5/11}    Approved
Hours
PK    ConFK        Date        AppHours
1    2        {^2017/7/3}    10
2    2        {^2018/3/12}    14
3    3        {^2018/4/1/}    20
4    3        {^2018/5/1}    12
Query: How many Consumers have a most recent Status of Approved, and
what is the sum of those Consumers' Approved Hours?
Answer: 2 Approved Consumers, having a total of 12 Hours.
I realize it's probably two queries: one for the sum of Consumers,
and
Post by Ken Dibble
one for the sum of Hours. However, I have been unable to figure out
how to write a simple query to get either of those two values.
I have laborious code that does things like pulling in all of the
Status records for each consumer and sorting them by date to find the
most recent one, and then doing the same for Hours records, and then
munging the data together into a final output cursor, and it works
fine and is fast enough, but it just makes me crazy every time
somebody wants a slightly different report along these lines.
It seems like there should be a way to do this more simply.
I am sure that I am missing something extremely obvious.
Thanks for any help.
Ken Dibble
www.stic-cil.org
_______________________________________________
http://mail.leafe.com/mailman/listinfo/profox
Post by Ken Dibble
http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions
of the author, and do not constitute legal or medical advice. This
statement is added to the messages for those lawyers who are too
stupid to see the obvious.
--
Frank Cazabon

Sent from my phone. Please excuse my brevity.

--- StripMime Report -- processed MIME parts ---
multipart/alternative
text/plain (text body -- kept)
text/html
---

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/C2DA0002-ED53-4C60-8B82-***@gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are
Ken Dibble
2018-06-21 18:28:10 UTC
Permalink
Post by Frank Cazabon
What's your expected output from the data you presented?
Answer: 2 Approved Consumers, having a total of 12 Hours.

I did include that in my original post.
Post by Frank Cazabon
To make it a little easier for people to try to help, here's some
code to build up the data and my attempt at what I've understood as
[snip]

Thank you for doing that. Wow, I'm sorry I omitted that. I usually do
that when I ask for help with queries.

Ken


_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Frank Cazabon
2018-06-21 18:33:26 UTC
Permalink
I mean specifically, which records (consumer PK and apphours) would you expect in your results?

Example: 2, 12 and 3, 14
Post by Ken Dibble
Post by Frank Cazabon
What's your expected output from the data you presented?
Answer: 2 Approved Consumers, having a total of 12 Hours.
I did include that in my original post.
Post by Frank Cazabon
To make it a little easier for people to try to help, here's some
code to build up the data and my attempt at what I've understood as
[snip]
Thank you for doing that. Wow, I'm sorry I omitted that. I usually do
that when I ask for help with queries.
Ken
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/2FCCFFBC-48CF-4961-B0E9-***@gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Ken Dibble
2018-06-21 18:53:24 UTC
Permalink
Post by Frank Cazabon
I mean specifically, which records (consumer PK and apphours) would
you expect in your results?
There are two Consumers whose most recent (last) status is
"Approved": Consumer PKs 1 and 3. The relevant Status records are
Status PKs 2 (for Consumer 1) and 8 (for Consumer 3).

Of those two Consumers, only Consumer 3 has any Hours records at all.
The value for Consumer 3's most recent (last) hours record is 12
(Hours record PK 4).

Thanks.

Ken


_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Frank Cazabon
2018-06-21 18:53:02 UTC
Permalink
For example, this query will bring out the 2 consumers whose last status
was approved:

SELECT Status.ConFK;
    FROM Status ;
    INNER JOIN (SELECT ConFK, MAX(Date) AS MaxDate;
        FROM Status;
        GROUP BY ConFK) M ON Status.ConFK = M.ConFK AND Status.Date =
M.MaxDate ;
    WHERE Type = "Approved"

That is 1 & 3

What records from the Hours table will give you the total of 12? Is it
just the one where HourPK = 4 and ConFK = 3 (since this is the latest
one for consumer 3 and there are no records for consumer 1 in the hours
table)?


Frank.

Frank Cazabon
Post by Ken Dibble
Post by Frank Cazabon
What's your expected output from the data you presented?
Answer: 2 Approved Consumers, having a total of 12 Hours.
I did include that in my original post.
Post by Frank Cazabon
To make it a little easier for people to try to help, here's some
code to build up the data and my attempt at what I've understood as
[snip]
Thank you for doing that. Wow, I'm sorry I omitted that. I usually do
that when I ask for help with queries.
Ken
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/5b806150-51a4-fb00-e6b8-***@gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those l
Frank Cazabon
2018-06-21 18:56:24 UTC
Permalink
Maybe this will do what you want:


SELECT Status.ConFK, LastHours.AppHours;
    FROM Status ;
    INNER JOIN (SELECT ConFK, MAX(Date) AS MaxDate;
        FROM Status;
        GROUP BY ConFK) M ON Status.ConFK = M.ConFK AND Status.Date =
M.MaxDate ;
    AND Type = "Approved";
LEFT JOIN (SELECT Hours.ConFK, Hours.AppHours;
            FROM Hours;
            INNER JOIN (SELECT ConFK, MAX(date) AS MaxHoursDate;
                            FROM Hours;
                            GROUP BY ConFK) MH ;
                        ON Hours.ConFK = MH.ConFK AND Hours.Date =
MH.MaxHoursDate ) LastHours ;
            ON Status.ConFK = LastHours.ConFK

Frank.

Frank Cazabon
Post by Ken Dibble
Post by Frank Cazabon
What's your expected output from the data you presented?
Answer: 2 Approved Consumers, having a total of 12 Hours.
I did include that in my original post.
Post by Frank Cazabon
To make it a little easier for people to try to help, here's some
code to build up the data and my attempt at what I've understood as
[snip]
Thank you for doing that. Wow, I'm sorry I omitted that. I usually do
that when I ask for help with queries.
Ken
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/af5ff9ae-944f-5a95-a0ff-***@gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvi
Ken Dibble
2018-06-22 17:04:12 UTC
Permalink
Post by Frank Cazabon
SELECT Status.ConFK, LastHours.AppHours;
FROM Status ;
INNER JOIN (SELECT ConFK, MAX(Date) AS MaxDate;
FROM Status;
GROUP BY ConFK) M ON Status.ConFK =
M.ConFK AND Status.Date = M.MaxDate ;
AND Type = "Approved";
LEFT JOIN (SELECT Hours.ConFK, Hours.AppHours;
FROM Hours;
INNER JOIN (SELECT ConFK, MAX(date) AS MaxHoursDate;
FROM Hours;
 GROUP BY ConFK) MH ;
 ON Hours.ConFK =
MH.ConFK AND Hours.Date = MH.MaxHoursDate ) LastHours ;
ON Status.ConFK = LastHours.ConFK
Yes, using the data I provided (and which you
assembled into tables), this gets:

CONFK APPHOURS
1 .NULL.
3 12

The query itself doesn't sum anything, but I
assume I can convert NULLs to 0 and sum the
APPHOURS column, and use _TALLY or RECCOUNT() to
provide a total of approved Consumers.

Thank you very much!!!

Ken


_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Frank Cazabon
2018-06-22 17:21:09 UTC
Permalink
You just need to change the first line of the query to this:

SELECT COUNT(Status.ConFK) AS ConsCount, SUM(LastHours.AppHours) AS
HoursSum;


Frank.

Frank Cazabon
Post by Frank Cazabon
SELECT Status.ConFK, LastHours.AppHours;
    FROM Status ;
    INNER JOIN (SELECT ConFK, MAX(Date) AS MaxDate;
        FROM Status;
        GROUP BY ConFK) M ON Status.ConFK = M.ConFK AND Status.Date =
M.MaxDate ;
    AND Type = "Approved";
LEFT JOIN (SELECT Hours.ConFK, Hours.AppHours;
            FROM Hours;
            INNER JOIN (SELECT ConFK, MAX(date) AS MaxHoursDate;
                            FROM Hours;
                            GROUP BY ConFK) MH ;
                        ON Hours.ConFK = MH.ConFK AND Hours.Date =
MH.MaxHoursDate ) LastHours ;
            ON Status.ConFK = LastHours.ConFK
Yes, using the data I provided (and which you assembled into tables),
CONFK   APPHOURS
1               .NULL.
3               12
The query itself doesn't sum anything, but I assume I can convert
NULLs to 0 and sum the APPHOURS column, and use _TALLY or RECCOUNT()
to provide a total of approved Consumers.
Thank you very much!!!
Ken
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/b57c867d-3680-0e08-5120-***@gmail.com
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the ob
Ken Dibble
2018-06-25 14:39:14 UTC
Permalink
Frank,

Just to close out this discussion:

The code you provided worked perfectly. I've also
demonstrated that if the user wants results for
Consumers with more than one option for Current
Status (ie, those who are "approved" or "on
hold"), I can simply add a UNION clause with the
same query and that works just fine.

Thank you very much for this.

Ken

PS: The jumble below is what happens when people
use Outlook's proprietary HTML code to send email
to people who don't use Outlook. Sending in plain text fixes this problem.
Content-Transfer-Encoding: base64You just need
SELECT COUNT(Status.ConFK) AS ConsCount, SUM(LastHours.AppHours) AS HoursSum;
Frank.
Frank Cazabon
€£M1
PMхÑÕ̹
½¹,°1…ÍÑ!½ÕÈs.AppHours;
Post by Frank Cazabon
FROM Status ;
INNER JOIN (SELECT ConFK, MAX(Date) AS MaxDate;
0¨0¨0¨0¨0¨0¨0¨”€OM Status;
ˆ0¨0¨0¨0¨0¨0¨0¨Ô“ÕT­HÛۑ’ÊHHӈÝ]\ˀConFK =
M.ConFK AND Status.Date = ˆK“X^]Hƒâ** AND Type = "Approved";
ˆQ•“ÒSˆ
ÑSPÕÝ\œËÛۑ€K, Hours.AppHours;
0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨”“ÓHÝ\œÎ€>>
INNER JOIN (SELECT ConFK, MAX(date) AS MaxHoursDate;
0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨ FROM Hours;
ˆ0¨0¨0¨0¨0¨0¨0¨0¨0¨0€  GROUP BY ConFK) MH ;
0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0¨0à°¨0¨0¨0¨0¨ÓˆÀurs.ConFK
= MH.ConFK AND Hours.Date =
Post by Frank Cazabon
MH.MaxHoursDate ) LastHours ;
ON Status.ConFK = LastHours.ConFK
Y\Ë\Ú[™ÈH]HH›ÝšYY
[™ which you assembled into tables),
CONFK APPHOURS
1 .NULL.
3 12
ˆH]Y\žH]Ù[ˆÙ\Àn't sum anything, but I assume I can convert
NULLs to 0 and sum the APPHOURS column, and use
_TALLY or RECCOUNT() to provide a total of approved Consumers.
[šÀ you very much!!!
Ù[‚€¥¶W†6W76—fRV÷F­ær&VÖ÷fVB' server]
[excessive quoting removed by server]

_______________________________________________
Post Messages to: ***@leafe.com
Subscription Maintenance: http://mail.leafe.com/mailman/listinfo/profox
OT-free version of this list: http://mail.leafe.com/mailman/listinfo/profoxtech
Searchable Archive: http://leafe.com/archives/search/profox
This message: http://leafe.com/archives/byMID/profox/
** All postings, unless explicitly stated otherwise, are the opinions of the author, and do not constitute legal or medical advice. This statement is added to the messages for those lawyers who are too stupid to see the obvious.
Loading...