Re: [PHP-DB] Re: Date operations.

2002-01-31 Thread DL Neil

Frank,

As yet no response from Garry, but I wanted to ask:
You already have DateTable set up (presumably), so extending its application into a 
relationship with the
breeding table is no big deal. Given that one suggestion was that Garry could consider 
storing monthly
statistics in another table (from breeding), and thus saves processing each time/only 
needs to update once per
month and presumably only for the month just passed; wouldn't it make sense FOR HIM to 
combine the two
functions? Initially create the MonthlyStats table to contain only year and month data 
(which can be related to
'drive' date-oriented SELECTing), and then update/populate each month's row as and 
when the stats become
available. It might also offer opportunities to simplify the processing outlined below.

Your thoughts?
=dn


- Original Message -
From: Frank Flynn [EMAIL PROTECTED]
To: [EMAIL PROTECTED]
Sent: 30 January 2002 17:05
Subject: [PHP-DB] Re: Date operations.


 Gary,

 You have a right to be confused - this problem is short but it is about as
 complex as they get.  Still I have a solution for you, also short and you'll
 (hopefully) find it elegant.  I found it interesting...

 The thing is we will create a Cartesian product on purpose - this is
 something they tell people learning SQL to avoid (and usually they are not
 helpful) but here it is the only to get a daily average since you don't have
 daily records of your pairs just a start and stop date.

 I was looking at the problem from the child point of view in my first post
 (easier since children only have a single birthday).  I'll use your problem
 now.

 We will keep the DateTable and use your 'breeding' table but I will change
 the 'paired' and 'split' columns to int (you don't need to do this but it
 will make thing easier - some DBMS's will always put a time stamp in a Date
 field and this does screw thing up - it makes it harder to join on them).

 So we have:

   breeding
  ---
rec   SMALLINT PRIMARY KEY
sire  SMALLINT
dam   SMALLINT
pairedINT
split INT
num_offspring INT

 And

   DateTable
  
dayID   INT PRIMARY KEY
myDate  DATE
month   INT
yearINT
quarter INT

  /* and as discussed any other date related columns */


  I need to count how many pairs were breeding
  on a given day, and then average over the month.

 OK - fasten you seat belt :-0

 SELECT count(*), myDate
   FROM breeding, DateTable
   WHERE paired = dayID
AND split = dayID
AND month = 2
AND year = 2001
   GROUP BY myDay
   ORDER BY myDay

 /* you could have just as easily used a start and stop date */
 /* myDay = 2/1/2001 and myDate  3/1/2001 */

 This will give you output something like this (the total per day):
   5  Feb 1, 2001
   5  Feb 2, 2001
   5  Feb 3, 2001
   5  Feb 4, 2001
   5  Feb 5, 2001
   6  Feb 6, 2001
   6  Feb 7, 2001
   6  Feb 8, 2001
   6  Feb 9, 2001
   6  Feb 10, 2001
   6  Feb 11, 2001
 ... And so on ...


 To get the average per month I'd use a temporary table (a table you create
 just for this report or that is always there but empty except during this
 report)

 /* start with an empty table */
 CREATE TABLE TotalByDay
 ( total INT,
   dayID INT)

 /* --- or --- */

 TRUNCATE TABLE TotalByDay

 /* now fill it... */
 /* notice it the same SQL but I've gone back to */
 /* dayID (the INT) not the full date and I've done */
 /* the whole year so we can average per month */

 INSERT INTO TotalByDay
 SELECT count(*), dayID
   FROM breeding, DateTable
   WHERE paired = dayID
AND split = dayID
AND year = 2001
   GROUP BY dayID
   ORDER BY dayID


 /* OK almost there ...  Now to average by month */

 SELECT ave(total), month, year
   FROM TotalByDay, DateTable
   WHERE TotalByDay.dayID = DateTable.dayID
   GROUP BY month
   ORDER BY month


 Now you've got output like

  5  1 2001
  6  2 2001
  6  3 2001
  7  4 2001
  12  5 2001
  11  6 2001
  11  7 2001
  7  8 2001
  7  9 2001
  9  10 2001
  9  11 2001
  9  12 2001

 From here you convert the month INT back into a name.

 Feel free to writ back with any questions (it's headdy stuff) also I don't
 have a mySQL db handy to check the syntax against - hopefully I've
 remembered everything correctly.  The concept is sound, we do this all the
 time.

 The got ya's are the DateTable must be full (don't fill it to the end of
 this year and forget about it - next year your reports will be wrong)

 Frank


 
  Ouch, I'm getting a bit lost. I need to count how many pairs were breeding
  on a given day, and then average over the month. Playing with mysql I get
  for say the 1st day of the year:
 
  select count(*) from breeding
   where TO_DAYS(paired) = TO_DAYS('2002-1-1')
   AND TO_DAYS('2002-1-1') = TO_DAYS(split);
 
  That will give me the number of pairs breeding that day. Then I would have
  to loop through the year and keep track of number of pairs, days of months
  etc to get the monthly

[PHP-DB] Re: Date operations.

2002-01-29 Thread Frank Flynn

The traditional Data Warehouse way to solve this is to have a second table
of dates.  The table might  look like:

DateTable
   ---
dayID int,
myDate datetime

And you add all the  particular columns that you might ever want to search
on, like:

   month int,
   year int,
   dayOfYear, int
   quarter int

And then your table(s) only include the dayID (the integer - perhaps the
date too but it's not necessary, all your searching and grouping is done by
the ID).

PHP offers several data functions which may or may not meet your needs but
the important thing to remember is that next year the dayID must not go back
to 1 - rather tomorrow will always be dayID++.

So if your table looked like:

  Dog
 -
  name varchar(20),
  mom varchar(20),
  dad varchar(20),
  birthDayID int,
  sex char

You could do a query like:

  Select mom, count(*) from Dog
where birthDayID in
  (select dayID from DateTable where year = 2000)
  Group by mom

Which would show you all the mothers who had given birth in 2000 and the
number of children for each.  Now notice how easy it is to change the where
year = 2000 to where quarter = 2 and year = 2001 and so on...

 I need to generate some statistics to work out average numbers of pairs
 per month, averaged on a daily basis, for a given start and stop date,
 typically a year or year-to-date.

  Select month, count(*) from Dog, DateTable
where birthDayID = myDate
  and myDate = 1/1/2000 /*start date */
  and myDate  6/1/2000   /* end date */
   Group by month

-- this is the total per month for the first 5 months of 2000, you can
figure the average from here.  Change the month to quarter,  dayOfYear or
year or even myDate for daily totals and you're off.

This set up works best where the  number of records per day is high - you
only need one int field in your data table (sometimes  called 'fact table')
and  you can be as anal as you like with your DateTable - even go back and
add more attributes later without messing  with your fact table.

The advantage is you do the work on the DateTable and then it's a simple
join to your fact table.

Good Luck,
Frank   [EMAIL PROTECTED]

On 1/29/02 9:21 AM, [EMAIL PROTECTED]
[EMAIL PROTECTED] wrote:

 
 From: Garry Optland [EMAIL PROTECTED]
 Date: Tue, 29 Jan 2002 19:10:25 +1100 (EST)
 To: [EMAIL PROTECTED]
 Subject: Date operations.
 
 Hi All,
 
 I have a problem working out a suitable algorithm either in PHP or MySQL.
 
 Basically I have a DB that keeps track of breeding records. Each record
 has a paired data, and a split-up date.
 
 I need to generate some statistics to work out average numbers of pairs
 per month, averaged on a daily basis, for a given start and stop date,
 typically a year or year-to-date.
 
 All the algorithms I can think of are messy, where I have to loop through
 all the breeding records for every day of the year, and count how many
 pairs are breeding by seeing if the date is between the start and stop
 dates, and then average that on a monthly basis. I can't see
 that scaling very well, as there might be several hundred breeding records
 for a given year, multiplied by 365 days.
 
 Has anyone any hints/pointers for an efficient way to do this?
 
 Regards,
   Garry.
 


-- 
Frank Flynn
Poet, Artist  Mystic



-- 
PHP Database Mailing List (http://www.php.net/)
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
To contact the list administrators, e-mail: [EMAIL PROTECTED]