I have a query selecting rows between dates.
SELECT * FROM `table` WHERE statusDate >= '2014-10-01' AND statusDate <= '2014-10-31'
When I use the above query it returns significantly less rows than the following query...
SELECT * FROM `table` WHERE statusDate > '2014-09-30' AND statusDate < '2014-11-01'
Technically I'd have thought it would return the same results but it's not.
My understanding on the bottom query is that it selects from dates above and below the dates stated, not including. Why would the results be different?
If statusDate is a DATETIME column, the time of day will cause the results to be different for rows on the last day of the month. When you convert the date 2014-10-31 to a DATETIME, it's 2014-10-31 00:00:00. If there's a row whose statusDate is 2014-10-31 09:23:11, it will not be selected by the first query, but it will be selected by the second query.
You can solve this by using:
WHERE statusDate >= '2014-10-01' AND DATE(statusDate) <= '2014-10-31'
or you can add the time to the WHER clause:
WHERE statusDate >= '2014-10-01' AND statusDate <= '2014-10-31 23:59:59'
Related
I have a problem with query where the conditions are related to TIMESTAMP column. So I have a table named table1 which has two columns start_time and end_time. Both of them store TIMESTAMP. I want to query my databse for a particular rows where end_time is higher than given timestamp value and lower than given timestamp value. Basically I want to get all the rows where end_time is between given TIMESTAMP range.
I have found that in my case following query works:
SELECT * FROM table1
WHERE UNIX_TIMESTAMP(end_time) >= FROM_UNIXTIME('2015-11-30 20:14:00')
AND UNIX_TIMESTAMP(end_time) <= FROM_UNIXTIME('2015-11-30 20:14:05')
But it is not what I want to. I want to give TIMESTAMP value instead of DATE.
What is also strange is that this query returns values that have end_time of earlier date than given timestamp:
SELECT * FROM table1 WHERE end_time > FROM_UNIXTIME( '2015-11-30 20:20:05' )
Query above returns rows where end_timestamp is 2015-11-30 20:18:05
I feel that I am missing something here. Should I use INT instead of TIMESTAMP for my end_time? I believe that the following query should return expected values but it gives me nothing:
SELECT * FROM table1
WHERE end_time >= FROM_UNIXTIME( 1448914740 )
AND end_time <= FROM_UNIXTIME( 1448914810 )
You don't need to convert your WHERE clause values using FROM_UNIXTIME. FROM_UNIXTIME converts a TIMESTAMP into a date. If you're sending values to the SQL statement that are already in TIMESTAMP format, your SQL will look like this:
SELECT * FROM table1 WHERE end_time >= 1448914740 AND end_time <= 1448914810
If you are sending date strings (e.g. '2015-11-30 20:14:00' and '2015-11-30 20:14:05') then your SQL would look like this:
SELECT * FROM table1 WHERE FROM_UNIXTIME(end_time) >= '2015-11-30 20:14:00' AND FROM_UNIXTIME(end_time) <= '2015-11-30 20:14:05'
Since you're storing your values in your table as TIMESTAMP I would recommend you use the first SQL statement.
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
Now, I've a problem with the following query:
SELECT *
FROM table
WHERE date > CURDATE()
OR date = CURDATE()
AND time > CURTIME()
It's return rows with date > of today but I need also rows with date of today but with time > of the current time.
You need to put the related clauses inside parenthesis:
SELECT *
FROM table
WHERE date > CURDATE()
OR (
date = CURDATE()
AND time > CURTIME()
)
You should use the appropriate date/time functions instead of complicating yourself with complex WHERE clauses:
SELECT * FROM TABLE
WHERE ADDTIME(date, time) > NOW()
More information on the ADDTIME function in this link.
I have the following dates in my table. How do I find a closest date from either today (if today's date is there) or if today's date is not there then the nearest past date?
2012-10-01 aa123
2012-10-02 aa43
2012-10-03 aa478
2012-10-04 aa40
2012-10-05 aa54
2012-10-06 de34
2012-10-07 a5434
2012-10-08 r4t
2012-10-09 x34
2012-10-10 q23
2012-10-11 b53
So if today is '2012-10-07' is then the record will be a5434. But if 2012-10-07 is missing then the record will be de34 which belongs to 2012-10-06 since that would be the closest past day from today.
I am not sure where to start on this one, so I haven't tried anything yet. Need a sql solution to this.
It's simple, just get one of the last date <= the current date:
$now = date("Y-m-d");
$sql = "SELECT * FROM date_table where date_field <= '$now' ORDER BY date_field DESC LIMIT 1 OFFSET 1";
Add an ORDER BY statement to the query. The following will order the rows by their date, with the latest at the top and oldest at the bottom.
SELECT `id`, `date` FROM `table` ORDER BY `date` DESC LIMIT 1;
I want to be able to fetch results from mysql with a statement like this:
SELECT *
FROM table
WHERE amount > 1000
But I want to fetch the result constrained to a certain a month and year (based on input from user)... I was trying like this:
SELECT *
FROM table
WHERE amount > 1000
AND dateStart = MONTH('$m')
...$m being a month but it gave error.
In that table, it actually have two dates: startDate and endDate but I am focusing on startDate. The input values would be month and year. How do I phrase the SQL statement that gets the results based on that month of that year?
You were close - got the comparison backwards (assuming startDate is a DATETIME or TIMESTAMP data type):
SELECT *
FROM table
WHERE amount > 1000
AND MONTH(dateStart) = {$m}
Caveats:
Mind that you are using mysql_escape_string or you risk SQL injection attacks.
Function calls on columns means that an index, if one exists, can not be used
Alternatives:
Because using functions on columns can't use indexes, a better approach would be to use BETWEEN and the STR_TO_DATE functions:
WHERE startdate BETWEEN STR_TO_DATE([start_date], [format])
AND STR_TO_DATE([end_date], [format])
See the documentation for formatting syntax.
Reference:
MONTH
YEAR
BETWEEN
STR_TO_DATE
Use the month() function.
select month(now());
Try this:
SELECT *
FROM table
WHERE amount > 1000 AND MONTH(dateStart) = MONTH('$m') AND YEAR(dateStart) = YEAR('$m')
E.g.
$date = sprintf("'%04d-%02d-01'", $year, $month);
$query = "
SELECT
x,y,dateStart
FROM
tablename
WHERE
AND amount > 1000
AND dateStart >= $date
AND dateStart < $date+Interval 1 month
";
mysql_query($query, ...
This will create a query like e.g.
WHERE
AND amount > 1000
AND dateStart >= '2010-01-01'
AND dateStart < '2010-01-01'+Interval 1 month
+ Interval 1 month is an alternative to date_add().
SELECT Date('2010-01-01'+Interval 1 month)-> 2010-02-01
SELECT Date('2010-12-01'+Interval 1 month)-> 2011-01-01
This way you always get the first day of the following month. The records you want must have a dateStart before that date but after/equal to the first day of the month (and year) you've passed to sprintf().
'2010-01-01'+Interval 1 month doesn't change between rows. MySQL will calculate the term only once and can utilize indices for the search.
Try this
SELECT *
FROM table
WHERE amount > 1000
AND MONTH(datestart)
GROUP BY EXTRACT(YEAR_MONTH FROM datestart)
Try this if(date field is text then convert this string to date):
SELECT * FROM `table_name` WHERE MONTH(STR_TO_DATE(date,'%d/%m/%Y'))='11'
//This will give month number MONTH(STR_TO_DATE(date,'%d/%m/%Y'))
//If its return 11 then its November
// Change date format with your date string format %d/%m/%Y
Works in: MySQL 5.7, MySQL 5.6, MySQL 5.5, MySQL 5.1, MySQL 5.0, MySQL 4.1, MySQL 4.0, MySQL 3.23
Day:
SELECT EXTRACT(DAY FROM "2017-06-15");
Month:
SELECT EXTRACT(MONTH FROM "2017-06-15");
Year:
SELECT EXTRACT(YEAR FROM "2017-06-15");