I am having a serious issue I can not figure out. I am trying to return rows from MySQL database that have a Start date between two given dates and an End date as well. Here is my php code to query the database:
$getRooms = mysql_query("
SELECT *
FROM Tarifas
WHERE Start BETWEEN '2013-01-10' AND '2013-01-13'
AND End BETWEEN '2013-01-10' AND '2013-01-13'
");
Start and End are set up as DATE fields
my database is set up as follows:
ID | RoomId | Start | End
--------------------------------------
4 | 34562 | 2013-01-09 | 2013-10-23
If anyone can help me figure out why this is not working, it would be greatly appreciated!!
Looking at your query and sample data, perhaps you are looking for a SQL Query to Find Overlapping or Conflicting Date Ranges. The query would be:
SELECT *
FROM Tarifas
WHERE '2013-01-13' >= `Start` AND `End` >= '2013-01-10'
2013-01-13 is greater than 2013-01-09 -- and -- 2013-10-23 is greater than 2013-01-10 so Tarifas #4 will be returned since it conflicts/overlaps with the specified dates.
Related
I have this certain problem about mysql date functions.
I'm trying to compare the value of THIS MONTH to the given timestamp in database.
For example, month today is june, and the timestamp is 1369967316
And I'm trying to determine if that timestamp is in month of june.
$query = db_query("SELECT * FROM users WHERE MONTH(FROM_UNIXTIME(CURDATE())) = MONTH(1369967316)");
//count total members this mont
$members_month = $query->rowCount();
so if I used the rowCount, the $members_month should have the value of 1.
Unfortunately it doesn't work.
Any help would be appreciated.
Well I saw some answers that some kind of relevant to mine but it doesn't hit the spot or I didn't applied it well.
mysql get month from timestamp not working
how to use curdate() in where clause against unixtimestamp (bigint) column
This works for me:
mysql> SELECT MONTH(FROM_UNIXTIME(1369967316));
+----------------------------------+
| MONTH(FROM_UNIXTIME(1369967316)) |
+----------------------------------+
| 5 |
+----------------------------------+
Your issue is likely coming from the fact that 1369967316 is May 30th, not June (as you expect), thus resulting in an inequality with MONTH(CURDATE()).
mysql> SELECT FROM_UNIXTIME(1369967316);
+---------------------------+
| FROM_UNIXTIME(1369967316) |
+---------------------------+
| 2013-05-30 22:28:36 |
+---------------------------+
for e.g
SELECT *
FROM api_call_log
WHERE account_sid='XXXXXXXXXXXX' AND
created_time >= 01-02-2016 00:00:00 AND
created_time <= 31-02-2016 23:59:59
ALLOW FILTERING
I am getting records from first month as well though I searched for second month.
It's difficult to say without seeing your table structure or relevant portions of your result set. But I did notice that you are not specifying a GMT offset, which means you are effectively querying by your default local offset. The problem, is that Cassandra stores by GMT+0000.
For example, if you have a negative GMT offset of say -0600 (like me), a query for GMT-0600 would miss 6-hours-worth of data from February 1st. For instance, if I have a row out there for 2016-02-01 01:00:00+0000, this query will not return it:
aploetz#cqlsh:stackoverflow> SELECT * FROm events WHERe monthbucket='201602'
AND eventdate >= '2016-02-01 00:00:00';
monthbucket | eventdate | beginend | eventid | eventname
-------------+-----------+----------+---------+-----------
(0 rows)
And that's because 2016-02-01 01:00:00+0000 is essentially 2016-01-31 19:00:00-0600. So if I add the GMT offset of 0000, I see the row.
aploetz#cqlsh:stackoverflow> SELECT * FROm events WHERe monthbucket='201602'
AND eventdate >= '2016-02-01 00:00:00+0000';
monthbucket | eventdate | beginend | eventid | eventname
-------------+--------------------------+----------+--------------------------------------+-------------------
201602 | 2016-02-01 01:00:00+0000 | b | 78d2c2b7-c4ec-408f-be37-eccc0c05727d | test month border
(1 rows)
My guess, is that you probably have the opposite problem (extra rows vs. missing rows) due to having a positive GMT offset. Not specifying your offset in your query could be why it is including rows from the previous month. And if that's the case, then you may want those rows.
Also, don't use ALLOW FILTERING. Like ever.
Try this
SELECT * FROM api_call_log WHERE account_sid='XXXXXXXXXXXX' AND jobs.created_at between '01-02-2016 00:00:00' and '31-02-2016 23:59:59';
And also check the DATE/TIME format of the date column
This question already has answers here:
mysql query room availability
(2 answers)
Closed 7 years ago.
Would like some logical help on formulating a MYSQL Query that gets results that isn't within the data of the table.
I have a table named schedule that has columns with data type 'time' that indicates when this certain schedule starts and ends and a foreign key referencing from table 'rooms' in which the schedule will take place. And in the php code in its search feature, I wanted to add a feature that shows results of rooms that are currently not being occupied by a schedule or is vacant. I added a jquery slider to specifically fetch the start time and end time the searcher wanted.
TABLE 'schedule'
room sched_start sched_end
1 09:00:00 10:00:00
1 11:00:00 12:00:00
2 07:30:00 08:30:00
2 11:30:00 13:00:00
For example, the searcher wanted to search a vacant room from 10:00:00 to 11:00:00. Basing from the database, the result should show that both rooms, room 1 and room 2, should be displayed in the search result as both rooms won't be occupied within the specified time of the searcher. I was thinking of comparing chronologically the schedule of all the similar rooms, the 'sched_end' of the first row or the first schedule and the sched_start of the succeeding row or the schedule and so on, so to determine whether there is a vacant time in between. Can anyone help me on this?
All helps and hates would be very much appreciated as I can be as much noob in MySQL-ing.
DROP TABLE IF EXISTS schedule;
CREATE TABLE schedule
(room INT NOT NULL
,schedule_start TIME NOT NULL
,schedule_end TIME NOT NULL
,PRIMARY KEY(room,schedule_start)
);
INSERT INTO schedule VALUES
(1,'09:00:00','10:00:00'),
(1,'11:00:00','12:00:00'),
(2,'07:30:00','08:30:00'),
(2,'11:30:00','13:00:00'),
(3,'09:30:00','10:30:00'),
(3,'11:00:00','12:00:00'),
(4,'10:30:00','10:45:00');
SET #start:= '10:00:00';
SET #end:= '11:00:00';
SELECT DISTINCT x.room
-- or whatever columns you want from whichever table you want
FROM schedule x
LEFT
JOIN schedule y
ON y.room = x.room
AND y.schedule_start < #end
AND y.schedule_end > #start
-- other tables can join in here
WHERE y.room IS NULL;
+------+
| room |
+------+
| 1 |
| 2 |
+------+
http://sqlfiddle.com/#!9/1b677/1
Just to demonstrate that #M0rtiis's solution is wrong...
SELECT DISTINCT room
FROM schedule
WHERE #end <= schedule_start
OR #start >= schedule_end;
+------+
| room |
+------+
| 1 |
| 2 |
| 3 |
+------+
What you need is to specifically exclude the rooms that are occupied in the given period.
SET #start = '10:00:01';
SET #end = '10:59:59';
SELECT *
FROM `schedule` -- you probably want to select from rooms here...
WHERE room NOT IN (
SELECT room
FROM `schedule`
WHERE sched_start BETWEEN #start AND #end
OR sched_end BETWEEN #start AND #end
OR #start BETWEEN sched_start AND sched_end
OR #end BETWEEN sched_start AND sched_end
);
Note that I compensated the "start inclusive" behaviour by adding one second to the start time and subtracting one second from the end time. You should do that before you feed the times to SQL, to avoid those calculations there.
This query filters all cases, including overlapping meetings.
Or, perhaps slightly more coherently:
SET #start:= '10:00:00';
SET #end:= '11:00:00';
SELECT DISTINCT room
FROM schedule
WHERE room NOT IN ( SELECT room
FROM schedule
WHERE schedule_start < #end
AND schedule_end > #start );
Also, you really need proper indexes if this query is to perform with more than just a couple of rows. Use the EXPLAIN function to help you.
Its bad idea to store there TIME. use DATETIME instead to cover cases where need_start - one day and need_end - another (next? or i want to be guest in your hotel for a week?) day.
But anyway, on what u have now try this
SELECT DISTINCT
room
FROM schedule
WHERE
'11:00:00' <= sched_start
OR
'10:00:00' >= sched_end
http://sqlfiddle.com/#!9/dafae/9
You can use BETWEEN operator.
SELECT *
FROM schedule
WHERE sched_end BETWEEN '10:00:00' AND '11:00:00'
I have a table with a kind of weird date format in a column as varchar - this is the format that the company has provided me with - the T in the middle seems to mess things up.
EVENTID | EVENT_DATE | EVENT_DURATION
1 | 2012-10-14T06:00 | 15
2 | 2012-10-14T06:15 | 11
3 | 2012-10-14T06:26 | 14
4 | 2012-10-14T06:40 | 10
ect...ect
I have php code to return the current time in the exact same format (with the weird 'T' in the middle'
$thisin = DateTime::createFromFormat('Y-m-d\TH:i', date('Y-m-d\TH:i'));
$thisin->setTimeZone(new DateTimeZone('UTC'));
$thisout= $thisin->format('Y-m-d\TH:i');
Assuming that today is the 14th and the current time is 06:21, how do i query the current row based on duration that matches "$thisout from php" and the next five rows (in the future).
Because the current time and date are returned from php as "2012-10-14T06:21" The query should output
2 | 2012-10-14T06:15 | 11 (Now SHowing)
3 | 2012-10-14T06:26 | 14
4 | 2012-10-14T06:40 | 10
ect ect
I have been scratching my head for hours, DATE_FORMAT() Doesn't seem to work, and I think it may be the T in the middle. I am aslo have to figure out how to use duration to determine if the current time applies to a specific row.
This does not work
SELECT DISTINCT EVENTID, EVENT DATE, EVENT_DURATION
FROM epg_event
WHERE DATE_FORMAT(EVENT_DATE, '%Y-%m-%dT%H:%i') >= DATE_FORMAT(NOW(), '%Y-%m-%dT%H:%i')
ORDER BY EVENT_DATE ASC LIMIT 5
Any Ideas?
You should load the date information into a Date column rather than a varchar column in the database. As previously noted this is the ISO format for dates.
Need to add in the interval.
where event_date + INTERVAL duration MINUTE >= NOW()
I'm not currently able to test it, but something like this might work:
SELECT DISTINCT EVENTID, EVENT_DATE, EVENT_DURATION
FROM epg_event
WHERE (event_date <= NOW()) AND (ADDTIME(event_date, INTERVAL event_duration MINUTE) >= NOW())
ORDER BY event_date ASC LIMIT 5
DATE_FORMAT() is meant for formatting a DATETIME field, not the other way around. And, as mentioned earlier, you event_date should be a DATETIME field and you should convert the time when you import the data to your database.
I'm building a simple availability calendar with PHP and MySQL.
I have a table which stores the available dates for a property (currently all of them are blocks of 7 days)
available_dates:
start_date DATE
end_date DATE
available_id INT PRIMARY KEY
property_id INT
booked TINYINT(1)
And a table of booked dates which references the available_id of my available_dates table:
bookings
booking_id INT
available_id INT
***user details***
I plan on having rows added to available_dates for each property to mark which dates can be booked, and then setting the booked flag on that table when somebody books that block.
What I'd like to do is show a list of dates (in blocks of x days, 7 in this case) that have no availability set - so the date does not appear in that table - for the next 24 months or so.
I'm having trouble wrapping my head around this and I know there is a simpler way to do it that my first ideas of looping through each property, then each block of 7 days, etc etc.
Can anyone enlighten me?
Update:
Thanks to #ZaneBien 's brilliant and comprehensive answer, I've managed to get the results I need by using his yeardate table & procedure.
What I've done is when the page that needs to show the dates with no availability set is requested, the PHP will call the procedure to add more yeardates if there aren't any for CURYEAR()+2.
Then to get my results, a slightly modified version of Zane's query:
SELECT
a.yeardate AS blockstart,
DATE_ADD(a.yeardate, INTERVAL 7 DAY) AS blockend
FROM
yeardates a
LEFT JOIN
available_dates b
ON(a.yeardate BETWEEN b.start_date AND b.end_date)
OR
(DATE_ADD(a.yeardate, INTERVAL 7 DAY) BETWEEN b.start_date AND b.end_date)
WHERE
b.date_id IS NULL AND WEEKDAY(a.yeardate)=5;
In my case, the blocks are of 7 days, saturday to saturday - so I added the second WHERE clause to the query so that I get distinct 1 week saturday to saturday blocks for each row, that happen one after the other.
So instead of:
+------------+------------+
| blockstart | blockend |
+------------+------------+
| 2012-01-01 | 2012-01-08 |
| 2012-01-02 | 2012-01-09 |
| 2012-01-03 | 2012-01-10 |
| 2012-01-04 | 2012-01-11 |
I get this:
+------------+------------+
| blockstart | blockend |
+------------+------------+
| 2012-01-07 | 2012-01-14 |
| 2012-01-14 | 2012-01-21 |
| 2012-01-21 | 2012-01-28 |
| 2012-01-28 | 2012-02-04 |
Which is exactly what I need. Thanks again to Zane for a great answer.
Understanding your question as Retrieve all 7 day interval blocks of the current and next year whose ranges do not overlap any interval blocks already existing in the available_dates table:
To work with all days of the current and next year, we have to create a separate table (yeardates) containing DATEs of all days of the current and next year. This will facilitate our OUTER JOIN operation in the retrieval query.
Code to define the yeardates table and insert dates:
CREATE TABLE yeardates
(
yeardate DATE NOT NULL,
PRIMARY KEY (yeardate)
) ENGINE = MyISAM;
DELIMITER $$
CREATE PROCEDURE PopulateYear(IN inputyear INT)
BEGIN
DECLARE i INT;
DECLARE i_end INT;
SET i = 1;
SET i_end = CASE WHEN inputyear % 4 THEN 365 ELSE 366 END;
START TRANSACTION;
WHILE i <= i_end DO
INSERT INTO yeardates VALUES (MAKEDATE(inputyear, i));
SET i = i + 1;
END WHILE;
COMMIT;
END$$
DELIMITER ;
CALL PopulateYear(2012);
CALL PopulateYear(2013);
The table is then created and contains all days of the current and next year. If we ever need to insert days for subsequent years, just CALL the procedure again with the year as the parameter (e.g. 2014, 2015, etc..).
Then we can get the 7-day blocks that don't overlap blocks in the available_dates table:
SELECT
a.yeardate AS blockstart,
DATE_ADD(a.yeardate, INTERVAL 7 DAY) AS blockend
FROM
yeardates a
LEFT JOIN
available_dates b ON
(a.yeardate BETWEEN b.start_date AND b.end_date)
OR
(DATE_ADD(a.yeardate, INTERVAL 7 DAY) BETWEEN b.start_date AND b.end_date)
WHERE
b.available_id IS NULL
That retrieves all free 7-day blocks based on the bookings of all properties, but if we need to get the free 7-day blocks for just a particular property, we can use:
SELECT
a.yeardate AS blockstart,
DATE_ADD(a.yeardate, INTERVAL 7 DAY) AS blockend
FROM
yeardates a
LEFT JOIN
(
SELECT *
FROM available_dates
WHERE property_id = <property_id here>
) b ON
(a.yeardate BETWEEN b.start_date AND b.end_date)
OR
(DATE_ADD(a.yeardate, INTERVAL 7 DAY) BETWEEN b.start_date AND b.end_date)
WHERE
b.available_id IS NULL
Where <property_id here> is the property_id. We can even do the selection based on multiple properties at a time by simply changing it to WHERE property_id IN (<comma sep'd list of property_ids here>).
I think youve got it backwards.
All dates are potentially available unless booked, record what has been booked in the database and knock those out of your results