"Shaun" <[EMAIL PROTECTED]> wrote on 08/31/2005 04:56:23 PM:

> 
> <[EMAIL PROTECTED]> wrote in message 
> 
news:[EMAIL PROTECTED]
> > "Shaun" <[EMAIL PROTECTED]> wrote on 08/31/2005 04:04:20 PM:
> >
> >>
> >> <[EMAIL PROTECTED]> wrote in message
> >>
> > 
news:[EMAIL PROTECTED]
> >> > "Shaun" <[EMAIL PROTECTED]> wrote on 08/31/2005 02:43:33 
PM:
> >> >
> >> >> Hi,
> >> >>
> >> >> This query counts the number of entries in the Bookings table per
> > month,
> >> > is
> >> >> it possible for this query to return a zero where there are no
> > entries
> >> > for a
> >> >> particular month?
> >> >>
> >> >> SELECT COUNT(Booking_ID) AS "Num_Bookings"
> >> >> FROM Bookings
> >> >> WHERE User_ID = 1
> >> >> AND Work_Type_ID = 12
> >> >> AND DATE_FORMAT(Booking_Start_Date, "%m-%Y") >= "04-2005"
> >> >> AND DATE_FORMAT(Booking_Start_Date, "%m-%Y") <= "06-2005"
> >> >> AND Booking_Type = "Booking"
> >> >> GROUP BY MONTH(Booking_Start_Date)
> >> >> ORDER BY Booking_Start_Date
> >> >>
> >> >> Thanks for your help.
> >> >>
> >> >
> >> > You cannot have missing month values in your query result unless
> > provide
> >> > values to fill the gaps with. The easiest way to do that is to 
create
> > a
> >> > simple lookup table.
> >> >
> >> > CREATE TABLE monthList (
> >> >        id int,
> >> >        name varchar(18) not null
> >> > )
> >> >
> >> > INSERT monthList (id, name) values (1,'January'),(2,'February'),...
> > fill
> >> > in the rest...,(12,'December');
> >> >
> >> > Now you can have something to show even if your Bookings data 
doesn't.
> >> > Here is how you would use it in your sample query:
> >> >
> >> > SELECT m.name, COUNT(b.Booking_ID) AS "Num_Bookings"
> >> > FROM monthList m
> >> > LEFT JOIN Bookings b
> >> >        ON m.id = MONTH(b.Booking_Start_Date)
> >> > WHERE b.User_ID = 1
> >> >        AND b.Work_Type_ID = 12
> >> >        AND b.Booking_Start_Date BETWEEN '2005-04-01' and 
'2005-06-30
> >> > 23:59:59'
> >> >        AND b.Booking_Type = "Booking"
> >> > GROUP BY m.name
> >> > ORDER BY m.id;
> >> >
> >> > Since I am comparing date values to date values, this should 
process
> > much
> >> > faster (especially if Booking_Start_Date is the leftmost column in 
any
> >> > index). The short date format works for April 1 because any date
> > constant
> >> > without a time value is considered to be midnight (00:00:00). I had 
to
> >> > include the last second of June 30 so that you would detect 
bookings
> > that
> >> > happened on that date (so you searched across the whole day and 
didn't
> >> > just stop at midnight at the start of the day). An alternative to
> > using
> >> > the BETWEEN...AND... comparitor for date ranges is to look for 
"less
> > than
> >> > the next day".
> >> >
> >> > SELECT m.name, COUNT(b.Booking_ID) AS "Num_Bookings"
> >> > FROM monthList m
> >> > LEFT JOIN Bookings b
> >> >        ON m.id = MONTH(b.Booking_Start_Date)
> >> > WHERE b.User_ID = 1
> >> >        AND b.Work_Type_ID = 12
> >> >        AND b.Booking_Start_Date >= '2005-04-01'
> >> >        AND b.Booking_Start_Date < '2005-07-01'
> >> >        AND b.Booking_Type = "Booking"
> >> > GROUP BY m.name
> >> > ORDER BY m.id;
> >> >
> >> > And, just as an example, here is how you would handle the case 
where
> > you
> >> > wanted a month-by-month report that crosses over from one year to 
the
> >> > next. This should show how many bookings you had in each month for 
the
> >> > twelve months starting with April 2004.
> >> >
> >> > SELECT m.name as month, YEAR(b.Booking_Start_Date) as year,
> >> > COUNT(b.Booking_ID) AS "Num_Bookings"
> >> > FROM monthList m
> >> > LEFT JOIN Bookings b
> >> >        ON m.id = MONTH(b.Booking_Start_Date)
> >> > WHERE b.User_ID = 1
> >> >        AND b.Work_Type_ID = 12
> >> >        AND b.Booking_Start_Date >= '2004-04-01'
> >> >        AND b.Booking_Start_Date < '2005-04-01'
> >> >        AND b.Booking_Type = "Booking"
> >> > GROUP BY 1, 2
> >> > ORDER BY 1, m.id;
> >> >
> >> > (NOTE: I used a MySQL-specific shortcut by using column numbers in 
the
> >> > GROUP BY and ORDER BY clauses. A more ANSI way of writing those
> > clauses
> >> > would have been:
> >> >
> >> > GROUP BY YEAR(b.Booking_Start_Date), m.name
> >> > ORDER BY YEAR(b.Booking_Start_Date), m.id;
> >> >
> >> > I think the shortcut method is just a tad easier to read.)
> >> >
> >> >
> >> >
> >> > HTH!
> >> >
> >> > Shawn Green
> >> > Database Administrator
> >> > Unimin Corporation - Spruce Pine
> >>
> >> Hi Shawn,
> >>
> >> Thanks for your reply but the query doesnt seem to work for me...
> >>
> >> mysql> SELECT M.Month_Name,
> >>     -> COUNT(B.Booking_ID) AS "Num_Bookings"
> >>     -> FROM Months M
> >>     -> LEFT JOIN Bookings B
> >>     -> ON M.Month_ID = MONTH(B.Booking_Start_Date)
> >>     -> WHERE B.User_ID = 1799
> >>     -> AND B.Booking_Start_Date >= '2005-01-01'
> >>     -> AND B.Booking_Start_Date < '2005-12-01'
> >>     -> AND B.Booking_Type = "Booking"
> >>     -> GROUP BY M.Month_Name
> >>     -> ORDER BY M.Month_ID;
> >> +------------+--------------+
> >> | Month_Name | Num_Bookings |
> >> +------------+--------------+
> >> | May        |            3 |
> >> | June       |           22 |
> >> | July       |           12 |
> >> | August     |           15 |
> >> | September  |           13 |
> >> | October    |           18 |
> >> | November   |            6 |
> >> +------------+--------------+
> >> 7 rows in set (0.04 sec)
> >>
> >> mysql>
> >>
> >> Any ideas why this might be happening?
> >>
> >
> > It seems to be working just fine. You didn't get any December bookings
> > because the latest possible booking occurs before '2005-12-01 
00:00:00' .
> > If you want see December bookings, change your end date to 
'2006-01-01'
> >
> > If that wasn't it, can you explain WHY those numbers are wrong as I 
have
> > only the slimmest clue what your data is supposed to look like. If 
those
> > aren't the numbers you wanted, what numbers did you expect? Please,
> > provide sample queries to demonstrate what you expected and I can help 
you
> > figure out what we are missing.
> >
> > Shawn Green
> > Database Administrator
> > Unimin Corporation - Spruce Pine
> 
> Hi Shawn,
> 
> I understand the fact that December isn't there but what about January - 

> April? 
> 
> 

D'OH!  ROFL!

It's completely MY fault!! The date and other restrictions based on the 
Bookings table should have been part of the ON sub-clause of the LEFT JOIN 
(the word OUTER is optional with MySQL. LEFT JOIN is equivalent to LEFT 
OUTER JOIN). 

By leaving them in the WHERE clause, I made the dates a required part of 
the result when they should have applied to the optional portion of the 
data on the "right" side of the LEFT JOIN.

The corrected query should read:
SELECT m.name as month, YEAR(b.Booking_Start_Date) as year,
COUNT(b.Booking_ID) AS "Num_Bookings"
FROM monthList m
LEFT JOIN Bookings b
        ON m.id = MONTH(b.Booking_Start_Date)
        AND b.User_ID = 1
        AND b.Work_Type_ID = 12
        AND b.Booking_Start_Date >= '2004-04-01'
        AND b.Booking_Start_Date < '2005-04-01'
        AND b.Booking_Type = "Booking"
GROUP BY 1, 2
ORDER BY 1, m.id;

I am so very sorry! Modify my other examples in the same way and they 
should work too.

Shawn Green
Database Administrator
Unimin Corporation - Spruce Pine

Reply via email to