MySQL queries and intervals
This is the toughest query I ever made: http://robertr.pastebin.com/X4bG4pFp
"SELECT `user`.`id` , `user`.`fname` , `user`.`lname` ,
YEAR( `user`.`bday` ) AS `bday_year` , `user`.`class_id` ,
( SELECT `class`.`class_name`
FROM `wp_class_classes` `class`开发者_JS百科
WHERE `user`.`class_id` = `class`.`id`) AS `class_name`
FROM `wp_class_users` `user`
WHERE MONTH( `bday` ) = $month AND DAY( `bday` ) = $day
OR `user`.`fname` =
( SELECT `name`.`names`
FROM `wp_class_namedays` `name`
WHERE `name`.`day` = '$month.$day'
AND `user`.`fname` = `name`.`names` )
This query grabs data from three different database tables to check if there is someone in the database, who has a party today. And in Latvia we have Name Days too. Anyway, this query works well, and does its job well, but now I want to make it a bit cooler.
I want it to show, who will be having a party next week. You've probably noticed these emails that Facebook sends to you every weekend showing who has a birthday coming up.
But I just can't understand how to get at least that interval?
I remember that PHP has some good functions with which you can find on which day starts month and so on, but maybe here are some bright heart, and willing to help me kick me a bit faster forward.
SELECT
`user`.`id`,
`user`.`fname`,
`user`.`lname` ,
YEAR(`user`.`bday`) AS `bday_year`,
`user`.`class_id`,
(
SELECT
`class`.`class_name`
FROM `wp_class_classes` `class`
WHERE `user`.`class_id` = `class`.`id`
) AS `class_name`,
CASE
WHEN MONTH(`week`.`Date`) = MONTH(`user`.`bday`) AND
DAY(`week`.`Date`) = DAY(`user`.`bday`) THEN 1
ELSE 2
END AS `event_type`
FROM `wp_class_users` `user`
LEFT JOIN `wp_class_namedays` `name` ON `user`.`fname` = `name`.`names`
LEFT JOIN (
SELECT CURDATE() + INTERVAL (1 - DAYOFWEEK(CURDATE())) DAY AS `Date` UNION ALL
SELECT CURDATE() + INTERVAL (2 - DAYOFWEEK(CURDATE())) DAY UNION ALL
SELECT CURDATE() + INTERVAL (3 - DAYOFWEEK(CURDATE())) DAY UNION ALL
SELECT CURDATE() + INTERVAL (4 - DAYOFWEEK(CURDATE())) DAY UNION ALL
SELECT CURDATE() + INTERVAL (5 - DAYOFWEEK(CURDATE())) DAY UNION ALL
SELECT CURDATE() + INTERVAL (6 - DAYOFWEEK(CURDATE())) DAY UNION ALL
SELECT CURDATE() + INTERVAL (7 - DAYOFWEEK(CURDATE())) DAY
) `week`
ON CONCAT(MONTH(`week`.`Date`), '.', DAY(`week`.`Date`)) IN (
CONCAT(MONTH(`user`.`bday`), '.', DAY(`user`.`bday`)),
`name`.`day`
)
WHERE `week`.`Date` IS NOT NULL
The user table is joined with the name day table, and the result set is then compared against the dates of the current week. The final result set lists only those users whose birthdays or name days happen during the week.
If you want to know about the events of, for example, the next week, you can simply change the intervals in the week.Date
definitions as 8 - DAYOFWEEK...
, 9 - DAYOFWEEK...
etc.
One last thing is, instead of the correlated subquery in the select list you could use INNER JOIN
, like this:
SELECT
`user`.`id`,
`user`.`fname`,
`user`.`lname` ,
YEAR(`user`.`bday`) AS `bday_year`,
`user`.`class_id`,
`class`.`class_name`
FROM `wp_class_users` `user`
INNER JOIN `wp_class_classes` `class` ON `user`.`class_id` = `class`.`id`
LEFT JOIN `wp_class_namedays` `name` ON ... /* the rest of the above script */
The event_type
column as defined above can tell you whether the event is a birthday or not, but it doesn't let you know whether it's both the Birthday and a Name Day for that particular person.
In case you would like to have that distinction, you could change the event_type
definition like this:
CASE
WHEN MONTH(`week`.`Date`) = MONTH(`user`.`bday`) AND
DAY(`week`.`Date`) = DAY(`user`.`bday`) THEN 1
ELSE 0
END +
CASE CONCAT(MONTH(`week`.`Date`), '.', DAY(`week`.`Date`))
WHEN `name`.`day` THEN 2
ELSE 0
END AS `event_type`
Now the result of the column would be:
- 1 – a birthday
- 2 – a name day
- 3 – both
Additionally, you could have 'B'
instead of 1
and 'N'
instead of 2
(and ''
instead of 0
). The results would be then 'B'
, or 'N'
, or 'BN'
. Not sure whether +
can be used for concatenation, though. If not, put both CASE
s into CONCAT()
.
I'm not sure if I get your query right, but the command SYSDATE()
is mentioned in the MySQL docs. You might want to try something like:
... where date = SYSDATE() + 7
(check the syntax, I come from Oracle ;) )
This will get the parties for the next 7 days.
精彩评论