I just have a quick question, I am doing a cab booking system. I am finding troubles selecting the reservations within the next 2 hours in SQL. I don't need the whole reservation to appear when i select all, I only want within two hours from the time I run the query.
$query= "select Booking_No,
Email_Address,
Customer_Name,
Passenger_Name,
Phone_No,
concat(Unit_Number,'/', Street_Number,' ', Street_Name,',', Suburb) as Unit_Number,
Destination_Suburb,
Pickup_Date,
Pickup_Time from Booking1
where status = 'false'
and
(Pickup_Time >= DATE_FORMAT(NOW(), '%h:00:00') and
Pickup_Time <= DATE_FORMAT(NOW(), '%h') + interval 2 hour)";
Use the 'BETWEEN' clause in your WHERE clause.
WHERE status = 'false' AND Pickup_Time BETWEEN NOW() AND DATE_ADD(NOW(), INTERVAL 2 HOUR)
NOW() returns a date/time object, DATE_ADD() returns a date/time object. As long as your Pickup_Time is a date/time object, this will work like a treat!
Related
I got a table with two columns, timestamp (like '1405184196') and value.
I've saved some measured values.
$day= time()-84600;
$result = mysql_query('SELECT timestamp, value FROM table WHERE timestamp >= "'.$day.'" ORDER BY timestamp ASC');
This is how I get all values for the last 24h.
But is it possible to get average day values for the last month with a SQL statement or do I have to select all values of the last month and calculate the average of each day via PHP?
Several issues with Anish's answer:
1) This won't work if date+time is being stored in the timestamp field.
2) It assumes the OP means last month i.e June, May etc and not the last say 30 days.
This solves those issues:
SELECT DATE(`timestamp`) as `timestamp`, AVG(value)
FROM table
WHERE `timestamp` >= CURDATE() - INTERVAL 1 MONTH
GROUP BY DATE(`timestamp)
EDIT
Since the timestamp is a unix timestamp and the OP would like a calendar month:
SELECT DATE(FROM_UNIX(`timestamp`)) as `timestamp`, AVG(value)
FROM table
WHERE MONTH(FROM_UNIX(`timestamp`)) = MONTH(NOW() - 1)
GROUP BY DATE(FROM_UNIX(`timestamp))
You can do this:-
SELECT timestamp, AVG(value)
FROM table
GROUP BY timestamp
HAVING MONTH(timestamp) = MONTH(NOW()) - 1;
This query calculates average for last month.
DEMO
I have a database with the rows: SearchTerm | userId | date | historyId
I need to get the amount of entries every hour in the last 24 hour period where the userId=userid.
So far I have as follows:
$stmt = $conn->prepare("SELECT historyId FROM webHistory WHERE date >= now() - INTERVAL 1 DAY GROUP BY HOUR(date) AND userId=?");
I'm now a little stuck, how would I go about getting the num_rows for each hour group? I though about using count(*), but would this be the right method, if so how would I go about doing this?
Lastly, for mobile displays I would need to group by every two hour period, is this possible as I can only seem to find documentation on HOUR(), possibly DATEPART()?
You just need count(*):
SELECT HOUR(date) as hr, historyId, COUNT(*) as num_rows
FROM webHistory
WHERE date >= now() - INTERVAL 1 DAY AND userId=?
GROUP BY HOUR(date);
The condition on userId goes in the where clause. It is good form to include the hour(date) in the select, so you know which hour a given count refers to.
EDIT:
To just get today's hours, hour can do:
SELECT HOUR(date) as hr, historyId, COUNT(*) as num_rows
FROM webHistory
WHERE date(date) = date(now()) AND userId=?
GROUP BY HOUR(date);
To list data by two-hour periods:
SELECT FLOOR(HOUR(date)/2) AS period,historyId FROM webHistory, COUNT(*) as num_rows
WHERE date >= now() - INTERVAL 1 DAY
GROUP BY date, period
We can use SQL BETWEEN operator
SELECT HOUR(date) as hr, historyId, COUNT(*) as num_rows
FROM webHistory
WHERE date BETWEEN SUBDATE(date(now()),1) AND date(now())
AND userId=?
GROUP BY HOUR(date);
I have the following relation in my schema:
Entries:
entryId(PK) auto_inc
date date
In order to count the total entries in the relation I use a query in my php like this:
$sql = mysql_query("SELECT COUNT(*) as Frequency FROM Entries WHERE date = '$date'");
My question is how can I count the number of entries for the CURRENT month..
You want a between query based on your date column.
WHERE date BETWEEN startdate AND enddate.
Between is equivalent to date >= startdate AND date <= enddate. It would of course be also possible to just use >= AND < explicitly which would simplify it a bit because you don't need to find the last day of the month, but just the first day of the following month using only DATE_ADD(..., INTERVAL 1 MONTH).
However startdate and enddate in this case would be derived from CURDATE().
You can use CURDATE(), MONTH(), DATE_ADD and STR_TO_DATE to derive the dates you need (1st day of current month, last day of current month). This article solves a similar problem and all the techniques needed are shown in examples that you should be able to adapt:
http://www.gizmola.com/blog/archives/107-Calculate-a-persons-age-in-a-MySQL-query.html
The first day of the current month is obvious YEAR-MONTH(CURDATE())-01. The last day you can calculate by using DATE_ADD to add 1 Month to the first day of the current month, then DATE_ADD -1 Days.
update-
Ok, I went and formulated the full query. Don't think str_to_date is really needed to get the index efficiency but didn't actually check.
SELECT count(*)
FROM entries
WHERE `date` BETWEEN
CONCAT(YEAR(CURDATE()), '-', MONTH(CURDATE()), '-', '01')
AND
DATE_ADD(DATE_ADD(CONCAT(YEAR(CURDATE()), '-', MONTH(CURDATE()), '-', '01'), INTERVAL 1 MONTH), INTERVAL -1 DAY);
Try this
SELECT COUNT(1) AS `Frequency`
FROM `Entries`
WHERE EXTRACT(YEAR_MONTH FROM `date`) = EXTRACT(YEAR_MONTH FROM CURDATE())
See EXTRACT() and CURDATE()
Edit: Changed NOW() to CURDATE() as it is more appropriate here
Try
$sql = mysql_query("SELECT COUNT(*) as Frequency FROM Entries WHERE MONTH(date) = MONTH(NOW()) );
I have this;
$long = "86400";
$query = "SELECT * FROM users WHERE unixdate = UNIX_TIMESTAMP()-$long
ORDER BY unixdate DESC";
But it doesn't work. I would like to show all new users within 24 hours
You can do that query completely in MySQL with
SELECT col1, col2, otherCols
FROM yourTable
WHERE timestamp_col > (NOW() - INTERVAL 24 HOUR)
The expression (NOW() - INTERVAL 24 HOUR) returns the date 24 hours ago. MySql is smart enough to handle comparisons between Time related column types.
If timestamp_col is not a time related type, but something like a varchar or int column you have to use FROM_UNIXTIME on the column or adjust the above query to read
SELECT col1, col2, otherCols
FROM yourTable
WHERE timestamp_col > UNIX_TIMESTAMP( NOW() - INTERVAL 24 HOUR )
See DATE_SUB and DATE_ADD in the MySql Manual.
Use > instead of =. At the moment, you are querying for entries created at a certain second which will hardly ever match.
You're looking for new users within the last 24h, not exactly 24h. So you have to use the > (greater than) operator instead of = (equals).
$long = "86400";
$query = "SELECT * FROM users WHERE unixdate > UNIX_TIMESTAMP()-$long ORDER BY unixdate DESC";
By the way, PHP has a function equivalent to MySQL UNIX_TIMESTAMP() function: time();
You must convert the timestamp file to date for the comparison.
SELECT * FROM table WHERE (from_unixtime(unixdate) >= NOW() - INTERVAL 1 DAY)
I'm looking for a best practice advice how to speed up queries and at the same time to minimize the overhead needed to invoke date/mktime functions. To trivialize the problem I'm dealing with the following table layout:
CREATE TABLE my_table(
id INTEGER PRIMARY KEY NOT NULL AUTO_INCREMENT,
important_data INTEGER,
date INTEGER);
The user can choose to show 1) all entries between two dates:
SELECT * FROM my_table
WHERE date >= ? AND date <= ?
ORDER BY date DESC;
Output:
10-21-2009 12:12:12, 10002
10-21-2009 14:12:12, 15002
10-22-2009 14:05:01, 20030
10-23-2009 15:23:35, 300
....
I don't think there is much to improve in this case.
2) Summarize/group the output by day, week, month, year:
SELECT COUNT(*) AS count, SUM(important_data) AS important_data
FROM my_table
WHERE date >= ? AND date <= ?
ORDER BY date DESC;
Example output by month:
10-2009, 100002
11-2009, 200030
12-2009, 3000
01-2010, 0 /* <- very important to show empty dates, with no entries in the table! */
....
To accomplish option 2) I'm currently running a very costly for-loop with mktime/date like the following:
for(...){ /* example for group by day */
$span_from = (int)mktime(0, 0, 0, date("m", $time_min), date("d", $time_min)+$i, date("Y", $time_min));
$span_to = (int)mktime(0, 0, 0, date("m", $time_min), date("d", $time_min)+$i+1, date("Y", $time_min));
$query = "..";
$output = date("m-d-y", ..);
}
What are my ideas so far? Add additional/ redundant columns (INTEGER) for day (20091212), month (200912), week (200942) and year (2009). This way I can get rid of all the unnecessary queries in the for loop. However I'm still facing the problem to very fastly calculate all dates that doesn't have any equivalent in database. One way to simply move the problem could be to let MySQL do the job and simply use one big query (calculate all the dates/use MySQL date functions) with a left join (the data). Would it be wise to let MySQL take the extra load? Anyway I'm reluctant to use all these mktime/date in the for loop. Since I have complete control over the table layout and code even suggestions with major changes are welcome!
Update
Thanks to Greg I came up with the following SQL query. However it still bugs me to use 50 lines of sql statements - build up with php - that maybe could be done faster and more elegantly otherwise:
SELECT * FROM (
SELECT DATE_ADD('2009-01-30', INTERVAL 0 DAY) AS day UNION ALL
SELECT DATE_ADD('2009-01-30', INTERVAL 1 DAY) AS day UNION ALL
SELECT DATE_ADD('2009-01-30', INTERVAL 2 DAY) AS day UNION ALL
SELECT DATE_ADD('2009-01-30', INTERVAL 3 DAY) AS day UNION ALL
......
SELECT DATE_ADD('2009-01-30', INTERVAL 50 DAY) AS day ) AS dates
LEFT JOIN (
SELECT DATE_FORMAT(date, '%Y-%m-%d') AS date, SUM(data) AS data
FROM test
GROUP BY date
) AS results
ON DATE_FORMAT(dates.day, '%Y-%m-%d') = results.date;
You definitely shouldn't be doing a query inside a loop.
You can group like this:
SELECT COUNT(*) AS count, SUM(important_data) AS important_data, DATE_FORMAT('%Y-%m', date) AS month
FROM my_table
WHERE date BETWEEN ? AND ? -- This should be the min and max of the whole range
GROUP BY DATE_FORMAT('%Y-%m', date)
ORDER BY date DESC;
Then pull these into an array keyed by date and loop over your data range as you are doing (that loop should be pretty light on CPU).
Another idea is not to use string inside the query. Transform the string parameter to datetime, on mysql.
STR_TO_DATE(str,format)
http://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html