MySQL Query for Date Part

瘦欲@ 提交于 2019-12-26 08:56:47

问题


I have two tables...

tblEvent
--------
id
date

tblEventRecurring
-----------------
event_id
date_part
end_date

The relationship is I can have an event that is either on one day (date in tblEvent) or recurs on an interval (Day, Week, Month, Year) which ties in the tblEventRecurring table.

For example, if I put in an event for Feb. 10 recurring until Feb. 28 I'd have...

tblEvent
--------
id = 1
date = 2012-02-10

tblEventRecurring
-----------------
event_id = 1
date_part = D
end_date = 2012-02-28

what is the best way structure a query to get all dates where the following conditions are met...

  • tblEvent.date = today
  • if tblEventRecurring.date_part = D and today < end_date
  • if tblEventRecurring.date_part = W and today is the same day of week (sun-sat) as tblEvent.date and < end_date
  • if tblEventRecurring.date_part = M and today is the same day of month as tblEvent.date and < end_date etc.

Is there one solution more efficient than another? Is this a good time to use IF or CASE or a bunch of AND/OR statements?

Thanks for any guidance. D.

Since I was down voted for not researching, I thought I'd post my final query... I was struggling with some of the AND/OR and parentheses. I DID research and was reading more on CASE which I've never used so I hoped someone could possibly guide my query using it.

# where the current date is 2012-02-12
SELECT e.record_id, e.event_date, 
       DATE_FORMAT(e.event_time, '%l:%i %p') AS event_time, 
       e.category, pm.person_id, pm.status, pm.active
FROM tblEvent e 
JOIN tblTABLE pmd ON pmd.record_id = e.reference_id 
JOIN tblTABLE2 pm ON pm.record_id = pmd.t_id 
LEFT OUTER JOIN tblEventRecurring er ON er.event_id = e.record_id 
WHERE e.category = 'CAT' 
AND pm.planet_id = 1 # id of person
AND pm.active = 1 
AND pm.status = 'Read Only' 
AND (
    e.event_date = '2012-02-12' # the event is on current date
    OR ( 
        # recurring with no end date or end date in future
        er.end_date = '0000-00-00' OR er.end_date >= '2012-02-12'
        AND ( 
            e.event_date <= '2012-02-12' # recurring starts today or in past
            AND ( # meets any of the following
                (er.date_part = 'D') 
                OR (er.date_part = 'W' AND dayofweek('2012-02-12') = dayofweek(e.event_date)) 
                OR (er.date_part = 'M' AND dayofmonth('2012-02-12') = dayofmonth(e.event_date)) 
                OR (er.date_part = 'Y' AND (day('2012-02-12') = day(e.event_date) AND MONTH('2012-02-12') = MONTH(e.event_date)))
            ) 
        ) 
    )
)
ORDER BY e.event_time

回答1:


This is essentially the same as Mosty's answer but with the LEFT JOIN to retrieve events that occur only once. This will retrieve all events for today.

SELECT *
FROM `tblEvent`
LEFT JOIN `tblEventRecurring`
    ON `tblEvent`.`id` = `tblEventRecurring`.`event_id`
WHERE (`tblEvent`.`date` = CURRENT_DATE AND `tblEventRecurring`.`event_id` IS NULL)
OR (
    CURRENT_DATE BETWEEN `tblEvent`.`date` AND `tblEventRecurring`.`end_date`
    AND (
        (`tblEventRecurring`.`date_part` = 'D') OR
        (`tblEventRecurring`.`date_part` = 'W' AND DAYOFWEEK(`tblEvent`.`date`) = DAYOFWEEK(CURRENT_DATE)) OR
        (`tblEventRecurring`.`date_part` = 'M' AND DAYOFMONTH(`tblEvent`.`date`) = DAYOFMONTH(CURRENT_DATE))
    )
)

I am not sure whether this is of any use to you but thought I would post it as I have done it now

SELECT *
FROM `date_list`
LEFT JOIN (
    SELECT `tblEvent`.`id`, `tblEvent`.`date`, `tblEvent`.`name`, `tblEventRecurring`.`date_part`, `tblEventRecurring`.`end_date`
    FROM `tblEvent`
    LEFT JOIN `tblEventRecurring`
        ON `tblEvent`.`id` = `tblEventRecurring`.`event_id`
) AS `events`
    ON (
        `events`.`date` = `date_list`.`date`
    )
    OR (
        `date_list`.`date` BETWEEN `events`.`date` AND `events`.`end_date`
        AND (
            (`events`.`date_part` = 'D') OR
            (`events`.`date_part` = 'W' AND DAYOFWEEK(`events`.`date`) = DAYOFWEEK(`date_list`.`date`)) OR
            (`events`.`date_part` = 'M' AND DAYOFMONTH(`events`.`date`) = DAYOFMONTH(`date_list`.`date`))
        )
    )
WHERE `date_list`.`date` BETWEEN '2012-02-06' AND '2012-02-12'
ORDER BY `date_list`.`date`;

It assumes a date_list table consisting of a single date field containing a continuous list of dates.




回答2:


There aren't so many ANDs and ORs there. I think you're looking for something like this:

select * from tblEvent e
join tblEventRecurring er on e.id = er.event_id
where e.date = curdate() and curdate() < er.end_date and (
    (er.date_part = 'D') or
    (er.date_part = 'W' and dayofweek(curdate()) = dayofweek(e.date)) or
    (er.date_part = 'M' and dayofmonth(curdate()) = dayofmonth(e.date))
)

Anyway... shouldn't curdate() be <= than er.end_date?



来源:https://stackoverflow.com/questions/9232924/mysql-query-for-date-part

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!