How can you find MySQL data for the current week plus the following Sunday?
Given a date (e.g. Wednesday 5/18/11), it would show events from the previous Sunday to the next Sunday. 5/15/11 through 5/22/11.
The trick would be to find the 'previous' Sunday to a given date.
How can this be done?
SELECT *
FROM events
WHERE Yearweek(`eventdate`) = Yearweek(NOW())
OR ( Weekday(NOW()) = 6
AND Yearweek(`eventdate`) = Yearweek(
DATE_SUB(NOW(), INTERVAL 1 DAY)) )
Taking from Pentium's answer, with some adjustments...
SELECT
*
FROM
Events
WHERE
YEARWEEK(`eventdate`) = YEARWEEK(NOW()) OR
(
WEEKDAY(`eventdate`) = 6 AND
YEARWEEK(`eventdate`) = YEARWEEK(NOW()) + 1
)
This may need to be adjusted depending on the values for WEEKDAY (is 6 Sunday?).
Also, while this should work, my guess is that mySQL won't be able to use any indexes on the eventdate column with this method. It's probably better to find the actual dates themselves for the bordering Sundays and then do a BETWEEN or <= >=. This should allow the use of an index on the eventdate. Even if you don't have an index on it now, you might want to use one in the future.
Using a calendar table . . .
select cal_date
from calendar
where cal_date between
(select max(cal_date) from calendar
where cal_date <= '2011-05-15' and day_of_week = 'Sun') and
(select min(cal_date) from calendar
where cal_date > '2011-05-15' and day_of_week = 'Sun')
It's not clear what you want if the given date is a Sunday. This previous query returns 15 rows given a date that falls on Sunday. It returns 8 rows for all other days. You can tweak the comparison operators in the WHERE clause to get the behavior you want.
I posted code for a calendar table earlier on SO. It's for PostgreSQL, but you should be able to adapt it to MySQL without much trouble.
Related
I have player statistics which I would like to publish from certain dates.
At the moment I can see statistics in the database from the beginning.
SELECT name,
bankmoney AS Bank,
Playerkills AS 'Player Kills',
deathcount AS Deaths ,
aikills AS 'AI Kills',
teamkills AS 'Team Kills',
revivecount AS Revives ,
capturecount AS 'Territories Captured',
LastModified AS 'Last Seen'
FROM playerinfo
JOIN playerstats
ON playerinfo.UID = playerstats.PlayerUID
ORDER BY BankMoney DESC;
But I would like to present statistics from the start of the day and the start of the week.
How would I do that ?
Based on Spitfire's comments, to get the last 24 hours of data you can use INTERVAL and go back the required number of days you want. NOW() will give you the time the query was executed and BETWEEN will allow you to search between two days. So that part of the query could be:
WHERE 'Last Seen' BETWEEN NOW() AND NOW() - INTERVAL 1 DAY;
A week would require a change from 1 day to 7.
Try it.SELECT * from table_name where a.exam_date BETWEEN $date1 AND $date2;
for example if you want to see only statistics with lastModified greater or equal today just add a where clause:
WHERE 'Last Seen' >= CURRENT_DATE()
Trying to select a closest previous and next holiday from the database. Say, New Year's Day is always at the 1st of January, and New Year's Eve is at the 31st of December. Current year is completely irrelevant, so I'm trying to select previous holiday by day and month (New Year's Eve) with the following MySQL query:
SELECT * FROM `calendar` WHERE DATE_FORMAT(`holidayDate`, "%m-%d") < "01-01"
It gives NULL. I was expecting that it would drop through and will look in the previous month, December, but...
Tried a lot of different ways of doing it, but still no success.
P.S.: Cannot use TIMESTAMP in this case...
The reason it's returning null is because there isn't anything less than '01-01'. The query doesn't wrap around to the beginning.
What I would do is write a case statement that checks to see if you are at the earliest holiday.
If you are the earliest holiday, then you can select the latest holiday (a way of wrapping around).
If you are not the earliest holiday, then you need to select the one before it. I did this by ordering them in descending date, and limiting it to 1. (Effectively grabbing the holiday occurring before the current date.)
Try this:
SELECT *
FROM calendar
WHERE
CASE WHEN DATE_FORMAT(CURDATE(), '%m-%d') = DATE_FORMAT((SELECT MIN(c.holidayDate) FROM calendar c), '%m-%d')
THEN holidayDate = (SELECT MAX(c.holidayDate) FROM calendar c)
ELSE
DATE_FORMAT(holidayDate, '%m-%d') < DATE_FORMAT(CURDATE(), '%m-%d')
END
ORDER BY holidayDate DESC
LIMIT 1;
Here is an SQL Fiddle example. I created two queries. One that uses the current date (seen above) and one that has Jan 1st hard coded to show that the case statement does work. I've only added certain holidays to test.
If two queries are acceptable for you:
SELECT max(holidayDate) as prev_holiday from calendar where holidayDate < now();
SELECT min(holidayDate) as next_holiday from calendar where holidayDate > now();
I've been having a bit of trouble thinking this problem through. I can't seem to define a SELECT query which is accurate enough to give me the result I want.
I am storing shift patterns in a table. These shift patterns don't have any restrictions on when they can start and finish (except that they cannot overlap each other per machine)
This is the structure of the table (5 rows of example data)
The only information I have to select with is:
The current time (e.g. 01:45)
The current weekday (e.g. Tuesday)
The issue is when a shift overlaps 00:00. So my question is this:
How would I select the current shift based on the current time and weekday?
Here is an SQL Fiddle of the scenario
Thanks!
You can do this with simple logic. If StartTime < EndTime, then you want to test for times between the two values. If Startime > EndTime, then you want to test for times not between the two values. So this solves the time problem:
SELECT *
FROM webreportshiftsetup
WHERE (StartTime < EndTime and time(now()) between StartTime and EndTime or
StartTime > EndTime and time(now()) not between StartTime and EndTime
) and
dayname(now()) in (StartWeekDay, EndWeekDay)
You have a similar problem with the weekdays. But your question is specifically about times and not weekdays. (That should perhaps be another question.)
If your shifts are one-day (i.e. you need to select only current day) you can do something like
SELECT * FROM shifts
WHERE startWeekDay = DATE_FORMAT(CURDATE(),'%W') AND NOW() BETWEEN startTime AND endTime
Otherwise, if your shift starts on Monday and finishes on Wednesday, and today is Tuesday, you will have trouble finding todays shift with a query. For that you should store days as number: 1- Monday, 2- Friday, ...
I would suggest that you change the schema. One option is to use the datetime type for start/end, instead of using varchar for everything.
Then you can query it like:
SELECT *
FROM webreportshiftsetup
WHERE NOW() BETWEEN StartDateTime AND EndDateTime
and so forth.
If you need this to be a repeating thing to where specific dates won't work, then you might make the StartDay/EndDay columns tinyint and give them a value of 1-7, with the smallest number being the first day of the week and the largest number representing the last day of the week. StartTime/EndTime would be date type. Querying that would look like:
SELECT *
FROM webreportshiftsetup
WHERE StartDay >=2 AND EndDay <=4 AND StartTime >= '2:00' AND EndTime <= '13:00'
I want to retrieve data whose Date between start and end date is between today and after ten day.I'm doing it in rails but even if i get the query in MySQL i can convert it to rails active record.
Something like this one :
select * from users where( between users.from and users.to = between '2012-11-25 11:52:33' and '2012-12-05 11:52:33')
The interval (a, b) overlaps with (c, d) iff a < d and b > c. Also, the curdate() function returns the current date ("today"). To calculate the date ten days into the future you can use + interval 10 day.
Combining these bits of information you get:
select ... where users.to > curdate()
and users.from < curdate() + interval 10 day
Follwing is the logic snippet not the exact code though. Please try.
select * from users
where users.fromDate between '2012-11-25 11:52:33' and '2012-12-05 11:52:33'
and users.toDate between '2012-11-25 11:52:33' and '2012-12-05 11:52:33';
Check the following sample code in * SQLFIDDLE as well
EDITING AS PER YOUR QUESTION'S REPHRASING..
Guess you are better off with,
where users.from between users.from and users.from + interval 10day
and users.to <= user.from + interval 10 day
That means, your from date can be anything (today, yesterday, one month back, two years to future...). Hence your to-date will be validated against any date that is 10 days interval from the above from-date
Hope it makes sense... but again, Joni's answers fills for your today's consition. :)
I'm using a custom PHP function to produce a visual calendar for a single month that blocks out dates based on a table that contains an start date, and an duration - For example:
...This is produced by data saying that the table should be blocked out for 4 days from the 14th, and 7 days from the 27th.
The query looks something like this:
SELECT GROUP_CONCAT(DATE_FORMAT(start_date,'%d'),':', event_duration) AS info
FROM events
WHERE YEAR(start_date = '2012'
AND MONTH(start_date) = '07'
ORDER BY start_date
(You could safely ignore the group concat and return the data as individual rows, that doesn't really matter).
I'm looking for a modification to the query that would block out dates at the start of the month IF an event starts in the previous month, but its length takes it into the following.
For instance - in the above example, the event on the 27th is actually scheduled to last 7 days in the database, so if I ran the query for MONTH(start_date) = '08' I'd like to say the first two dates blocked out, which they wouldn't currently be, because the start date that would block it out is not in the month being selected.
I'm fairly sure there's a subquery or something in there to grab the rows, but I just can't think of it. Any takers?
EDIT
The answer from Salman below pointed me in the directon I wanted to go, and I came up with this as a way of getting carryovers from the previous month to show as '1st' of the month with the number of remaining days:
SELECT IF(MONTH(start_date) < '08', '2012-08-01', start_date) AS starter,
IF(MONTH(start_date) < '08', duration - DATEDIFF('2012-08-01',start_date), duration) AS duration
FROM EVENTS
WHERE YEAR(start_date) = '2012'
AND (MONTH(start_date) = '08' OR MONTH(start_date + INTERVAL duration DAY) = '08')
Obviously a lot of variables there to replace in PHP, so maybe there's an even better way?
Original Answer:
Assuming that the month in question is 2012-07, you need this query:
SELECT column1, column2, columnN
FROM `events`
WHERE `start_date` <= '2012-07-01'
AND `start_date` + INTERVAL `duration` DAY > '2012-07-01'
ORDER BY start_date
Revised Answer:
Apparently you need a query that checks for overlapping (or conflicting) dates. The example dates are 2012-07-01 through 2012-08-01 and the query is:
SELECT *
FROM events
WHERE '2012-08-01' > start_date
AND start_date + INTERVAL duration DAY > '2012-07-01'
ORDER BY start_date
To constrain the start date and interval, you can use SELECT ... CASE statement:
SELECT
CASE
WHEN start_date < '2012-07-01' THEN '2012-07-01'
ELSE start_date
END AS start_date_copy,
CASE
WHEN start_date < '2012-07-01' THEN duration - DATEDIFF('2012-07-01', start_date)
ELSE duration
END AS duration_copy,
FROM ...
The answer I was looking for, thanks to the other contributor for pointing me in the right direction and enabling me to solve it!
This is based on $yyyy and $mm coming from PHP (in my case, into a function call), and selecting individual rows rather than grouping:
SELECT start_date, duration
FROM reservations
WHERE YEAR(start_date) = '".$yyyy."'
AND MONTH(start_date) = '".$mm."'
UNION
SELECT '".$yyyy."-".$mm."-01',
duration - DATEDIFF('".$yyyy."-".$mm."-01',start_date)
FROM reservations
WHERE YEAR(start_date) = '".$yyyy."'
AND MONTH(start_date) < '".$mm."'
AND MONTH(start_date + INTERVAL duration DAY) = '".$mm."'
ORDER BY start_date