SQL Query for reservation dates that break a month end? - mysql

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

Related

Select MySQL data starting from a specific date

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()

mysql retrieve difference between current and last hour

For the below table, i would like to get the difference between last hour and current hour for col-D and col-E for each of the site.
As part of that I am trying to first get the latest (current) hour entries for each of the site, but the following query is only listing me the entries with endTime as 01:00:00, when i have entries upto 9.00AM
select distinct(mmeName), endDate, endTime, c_ratio, set_time from attach where
type='INIT' and Date(endDate)=curDate() and
Time(endTime) >= DATE_ADD(Time(endTime), INTERVAL -1 HOUR) group by mmeName;
Any help would be appreciated for the immediate issue and as well finding the difference between current and last hour.
EDITED
I think this is what you are looking for. This will give you any records where the endTime is one hour prior to the latest current time for each mmeName. The 'max' sub-select gets the latest end datetime for each mmeName, and the join back matches on record exactly one hour prior to that.
SELECT mmeName, endDate, endTime, c_ratio, set_time
FROM attach a
JOIN
(SELECT mmeName, CONCAT(endDate, ' ' , endTime) max_endDateTime
FROM attach
WHERE type = 'INIT'
ORDER BY endDate DESC, endTime DESC
) AS max ON max.mmeName = a.mmeName
AND max.max_endDateTime = DATE_ADD(CONCAT(endDate, ' ' , endTime), INTERVAL 1 HOUR)
WHERE type = 'INIT'
;
ORIGINAL
select mmeName, endDate, endTime, c_ratio, set_time
from attach
where type='INIT' and Date(endDate)=curDate() and
endTime >= DATE_SUB(now(), INTERVAL -1 HOUR)
group by mmeName;
Note: If there are multiple matching records for a given mmeName, this query will just grab one of them.
EDITED: You need drop the TIME() functions from the WHERE clause. Both would have the date and time and if you didn't, if you ran it between 12:00 AM to 1:00 AM it would not return any results.

SQL Query to restrict return dates to current month

I am trying to restrict my returned data to only those points that have start and end dates in the current month - active projects. It is behaving problematically because today is the last day of the month. I believe that tomorrow will be a problem as well (no June data included in the sample).
Here is my data set (Table 1):
Project User Effort Start_Date End_Date
------- ------- ------ -------- --------
Traffic Control DOMAIN\john.smith 0.1 5/1/2013 5/31/2013
Turboencabulator Analysis DOMAIN\mark.webber 0 5/1/2013 5/31/2013
Widget Calibration DOMAIN\mark.webber 0 5/1/2013 5/31/2013
Gizmo Creation DOMAIN\steve.green 0.1 5/1/2013 5/31/2013
Advanced Toolmaking DOMAIN\steve.green 0.6 5/1/2013 5/31/2013
Diesel Engine Diagnostics DOMAIN\steve.green 0.05 5/1/2013 5/31/2013
Cold Fusion Reactor Creation DOMAIN\steve.green 0.3 5/1/2013 5/31/2013
When using the following query today I get no returned results:
SELECT * FROM dbo.table1
WHERE Start_Date <= (getdate()) AND End_Date >= (getdate())
ORDER BY User, Start_Date
Yesterday it was returning just fine. I have data for June as well (not displayed in my sample) but I need to modify my statement such that it will reliably return data for the current month throughout the entirety of the month.
Answer - Correct WHERE statement (from comments in answer below):
WHERE (Month(Start_Date) <= Month((getdate())) AND Month(End_Date) >= Month((getdate()))) AND (YEAR(Start_Date) <= YEAR((getdate())) AND YEAR(End_Date) >= YEAR((getdate())))
Use TSQL Month function:
SELECT * FROM dbo.table1
WHERE Month(Start_Date) = Month(getdate()) AND Month(End_Date) = Month(getdate())
ORDER BY User, Start_Date
Just consolidate your WHERE statement into something like:
DATEDIFF(m, DATEFIELD, GETDATE()) = 0
The following query can take advantage of indexes since it does not perform calculations on every row. In addition, it returns as "active" any project that is active at any time during the month, e.g. a project that starts in the last week of the month and ends several months hence. And it's easy to test and modify since it separates the date arithmetic from the query.
declare #Today as Date = GetDate()
declare #StartOfMonth as Date = DateAdd( day, 1 - Day( #Today ), #Today )
declare #EndOfMonth as Date = DateAdd( day, -1, DateAdd( month, 1, #StartOfMonth ) )
select #Today as [Today], #StartOfMonth as [StartOfMonth], #EndOfMonth as [EndOfMonth]
select *
from Table1
where Start_Date <= #EndOfMonth and End_Date >= #StartOfMonth
You should try using convert(date, GetDate())GetDate().
Dates are represented as ticks, meaning smaller than seconds. if you compare GetDate() (which is 2013-05-31 11:09:45:1024 for exmaple, unsure about millisecond precision in mssql), it will always be greater than 2013-05-31, because of the hours/minutes/seconds. Your 2 choices are to compare YOURDATE >= Start_Date AND End_Date + 1 > YOURDATE, or YOURDATE >= Start_Date AND End_Date >= convert(date, YOURDATE)
First options asks for it to be stricly less than the morrow of the end date (so basically the very end of that day), second one asks for it to be within the same day as the end date, ignoring ticks. Both yields the exact same result, one of them is probably more performant, however I can't help on that side of things.
EDIT : or you can use the other two's answer, except that it will only work if you always use monthly periods. and in that case it would be simpler to redesign your database to only have a 1-12 field representing the month.
In MySql, I use something similar to update data within x number of days, perhaps something like:
start_date <= DATE_SUB(curdate(), INTERVAL 10 DAY);
Just change 10 to whatever number of days you need.
Try this for MySQL
select date(date_joined),count(*) from users where MONTH(date_joined)=MONTH(now()) and YEAR(date_joined)=YEAR(now()) group by date(date_joined);

What time does a SQL query like this one start and end?

I am using a SQL query like:
SELECT * FROM game_list
WHERE start_date <= DATE(NOW()) AND end_date >= DATE(NOW())
ORDER BY game_id DESC;
Now, what time will this actually start and end? I mean I know on what date but what will the time be, is it midnight, 12 am, pm or what?
If i understand correctly you want to show a game only if current time is between start time and end time,in that case what you need is actually:
SELECT * FROM game_list
WHERE DATE(NOW()) >= start_date AND DATE(NOW()) <= end_date
ORDER BY game_id DESC;
This way it should work properly
The only problem i could see is if you don't format your start_date and end_date correctly.
If your value is full time stamp,you should simply use NOW() or CURRENT_TIMESTAMP directly as it contains both date AND time
If your start_date is year month day eg: 2012-05-12 you should use CURDATE()
If your value is simply a day number,like 1...2...3...4..etc you should use DAY()
I would doublecheck what start_date returns and decide accordingly,for reference i would take a look here date and time in mysql
If you are asking how the DATE function works: it simply extracts the date part of a datetime.
see http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_date
SELECT DATE('2003-12-31 01:02:03');
-> '2003-12-31
This represents simply that day. Considered as datetime again it would become midnight(2003-12-31 00:00:00)
I think you want something like following
SELECT * FROM game_list
WHERE start_date <= DATE(NOW()) AND end_date >= DATE_SUB(NOW(), INTERVAL 1 DAY)
ORDER BY game_id DESC;
Above query fetch the records which starts before today and having end date greater than tomorrow's date

Find a date between start_date and end_date

I have a table of events with a recorded start and end time. I want to find all events that occur on a specific date. Some events started a year ago and some will continue farther ahead.
I would like to be able to pick for example May 20, 2010 and find all events occurring on that date.
SELECT * FROM yourTable
WHERE start_date >= '2010-01-01' AND end_date <= '2010-06-30'
This query will return all dates where start_date is on or after 1st Jan, 2010, and end_date is on or before 30th June, 2010.
select * from TableName
where '2010-05-20' >= start_date and '2010-05-20' <= end_date
This will give you all events that occur on a specific date, even if the start or send dates are on different days.
Try...
WHERE (((MONTH(start_date) >= MONTH(NOW())) && (MONTH(end_date) <= MONTH(NOW()))) && YEAR(start_date) >= YEAR(NOW()))
That would get you anything from 3/2010.
Or..
WHERE ((MONTH(start_date) >= MONTH(NOW())) && YEAR(start_date) >= YEAR(NOW())))
Would get you events after 3/2010 into the future, and nothing before that.
Or..
WHERE (start_date_var) BETWEEN start_date AND end_date
Simply, where (passed value) is between any event start and end date.
These should produce results. It depends on how you are executing the query. Are you accepting form/url arguments to change dates?
It's confusing though that you want to have all dates that are not expired, yet also want dates that occurred on a specific date. Where are you getting start_date from?
Assuming you have input parameters named #start_date and #end_date, and you want to find any event that overlaps that range:
select *
from TableName
where #start_date between start_date and end_date
or #end_date between start_date and end_date