tags:

views:

840

answers:

2

I have a table that contains a list of community events with columns for the days the event starts and ends. If the end date is 0 then the event occurs only on the start day. I have a query that returns the number of events happening on any given day:

SELECT COUNT(*) FROM p_community e WHERE 
    (TO_DAYS(e.date_ends)=0 AND DATE(e.date_starts)=DATE('2009-05-13')) OR
    (DATE('2009-05-13')>=DATE(e.date_starts) AND DATE('2009-05-13')<=DATE(e.date_ends))

I just sub in any date I want to test for "2009-05-13".

I need to be be able to fetch this data for every day in an entire month. I could just run the query against each day one at a time, but I'd rather run one query that can give me the entire month at once. Does anyone have any suggestions on how I might do that?

And no, I can't use a stored procedure.

+3  A: 

Try:

SELECT COUNT(*), DATE(date) FROM table WHERE DATE(dtCreatedAt) >= DATE('2009-03-01') AND DATE(dtCreatedAt) <= DATE('2009-03-10') GROUP BY DATE(date);

This would get the amount for each day in may 2009.

UPDATED: Now works on a range of dates spanning months/years.

Greg
I would add a few columns to the select, but yea this should do it.
Tom Ritter
That's all he put in the example so I went with that.
Greg
This would work if each event were a single date, but I'm dealing with a date range on each item. Each event spans from date_starts to date_ends, so if an event is May 10th to May 14th, I need to be able to recognize May 12th.
ChiperSoft
I think I might be confused by your explanation of the solution you are looking for.
Greg
Yeah, I think you got it backwards. Quassnoi seems to get what I'm trying to do.
ChiperSoft
+4  A: 

Unfortunately, MySQL lacks a way to generate a rowset of given number of rows.

You can create a helper table:

CREATE TABLE t_day (day INT NOT NULL PRIMARY KEY)

INSERT
INTO    t_day (day)
VALUES  (1),
        (2),
        …,
        (31)

and use it in a JOIN:

SELECT  day, COUNT(*)
FROM    t_day
JOIN    p_community e
ON      day BETWEEN DATE(e.start) AND IF(DATE(e.end), DATE(e.end), DATE(e.start))
GROUP BY
        day

Or you may use an ugly subquery:

SELECT  day, COUNT(*)
FROM    (
        SELECT  1 AS day
        UNION ALL
        SELECT  2 AS day
        …
        UNION ALL
        SELECT  31 AS day
        ) t_day
JOIN    p_community e
ON      day BETWEEN DATE(e.start) AND IF(DATE(e.end), DATE(e.end), DATE(e.start))
GROUP BY
        day
Quassnoi
Thanks, this is pretty much what I expected to do. I didn't know about the BETWEEN keyword tho, that's a lot nicer than what I came up with.
ChiperSoft