I'm attempting to consolidate the where clause on the column name. I require a single column to return positive on the condition, but the same condition applies for many columns. The brute force example is below, to check for dates between a certain range on several columns. I have the columns OR'd with the exact same condition.
SELECT * FROM foo
WHERE foo.date1 BETWEEN DATE_SUB( DATE_ADD(DATE(NOW()), INTERVAL 16 HOUR), INTERVAL 24 HOUR) and DATE_ADD(DATE(NOW()), INTERVAL 16 HOUR)
OR foo.date2 BETWEEN DATE_SUB( DATE_ADD(DATE(NOW()), INTERVAL 16 HOUR), INTERVAL 24 HOUR) AND DATE_ADD(DATE(NOW()), INTERVAL 16 HOUR);
I would prefer to do something along the lines of:
SELECT * FROM foo
WHERE (foo.date1 OR foo.date2) BETWEEN DATE_SUB( DATE_ADD(DATE(NOW()), INTERVAL 16 HOUR), INTERVAL 24 HOUR) and DATE_ADD(DATE(NOW()), INTERVAL 16 HOUR);
.. but have it still work for individual columns across rows.
I'm using MariaDB, but can adapt any solutions from other flavors of sql.
The first works; the second is bad syntax.
I prefer
BETWEEN NOW() + INTERVAL 16-24 HOUR
AND NOW() + INTERVAL 16 HOUR
If the 16 is due to timezones, consider using TIMESTAMP and/or setting your system time appropriately.
Related
I will need a little help here
Problem is - after WHERE clause I only need rows where CBI is Critical or HIGH or there is combination where CBI is Medium and Priority is 1.
Unfortunately I am still getting rows where e.g. CBI is medium and priority is 2
SELECT * FROM main_table WHERE (cbi='Critical' OR cbi='High' OR (cbi='Medium' AND priority='1'))
AND start_date BETWEEN (NOW() - INTERVAL 12 HOUR) AND NOW()
OR involvement_date BETWEEN (NOW() - INTERVAL 12 HOUR) AND NOW()
OR finnish_date BETWEEN (NOW() - INTERVAL 12 HOUR) AND NOW();
Your Problem are the or parts between the date selection. There must be brackets arround
SELECT * FROM main_table WHERE (cbi='Critical' OR cbi='High' OR (cbi='Medium' AND priority='1'))
AND (start_date BETWEEN (NOW() - INTERVAL 12 HOUR) AND NOW()
OR involvement_date BETWEEN (NOW() - INTERVAL 12 HOUR) AND NOW()
OR finnish_date BETWEEN (NOW() - INTERVAL 12 HOUR) AND NOW());
I have some table with a datetime column, and I want to fetch from it all results like this:
If I execute the query on 2016-01-28 11:12:24, I want to fetch all results from 3 days ago from that whole hour (11:00:00). So I'd get all rows between 2016-01-28 11:00:00 and 2016-01-28 11:59:59. How do I do this, so that I can benefit from index on this datetime column?
I have tried using WHERE DATE_FORMAT(o.created_at, '%Y-%m-%d %H:00:00') = DATE_FORMAT(NOW() INTERVAL -3 DAY, '%Y-%m-%d %H:00:00') but it is a function, so the query doesn't use an index.
The best solution is to do this:
WHERE o.created_at >= DATE_FORMAT(date_sub(now(), interval 3 day), '%Y-%m-%d %H:00:00') AND o.created_at < DATE_FORMAT(date_add(date_sub(now(), interval 3 day), interval 1 hour), '%Y-%m-%d %H:00:00')
Alternately, you can also do this but only with precision up to seconds:
WHERE o.created_at BETWEEN DATE_FORMAT(date_sub(now(), interval 3 day), '%Y-%m-%d %H:00:00') AND DATE_FORMAT(date_sub(now(), interval 3 day), '%Y-%m-%d %H:59:59')
The BETWEEN AND clause here still utilizes the Index as we have not used DATE_FORMAT function on the column o.created_at. It is also much more efficient if the selected data is less than 1/3rd of the total rows.
[Ref: http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html ]
Note: Thanks to #Used_By_Already for pointing out the issue with precision up to microseconds.
Instead of formating a new date with NOW() Interval - 3...., take a look at DateDiff(). This allows you to set the difference from NOW() to other days and set the measure unit.
How can I get records in a table between NOW() and the previous 3am?
This would be easy if it's 9am, but how do I write this if it's 2am? i.e I want the trades between DATE_SUB(CURDATE(), INTERVAL 21 HOURS) and NOW(). I'm looking for some code which can do both without needing to check the time in usercode and choose between two sql statements.
I'm sure there's a simple solution to this, but it's eluding me.
A simple idea is to subtract three hours and compare the date:
where date(date_sub(col, interval 3 hour)) = (case when hour(date) >= 3 then curdate() else date_sub(curdate(), interval 1 day)
Or, more explicitly, just do the comparison in SQL:
where (hour(date) >= 3 and date(col) = curdate()) or
(hour(date) < 3 and date(col) = date_sub(curdate(), interval 1 day)
I'll add my own answer (I finally gave up and explored using IF and found it could be used inside SELECT statements), but #Gordon Linoff might be better - I've no idea which of these is faster.
SELECT IF (NOW() > DATE_ADD(CURDATE(), INTERVAL 3 HOUR),
DATE_ADD(CURDATE(), INTERVAL 3 HOUR),
DATE_SUB(CURDATE(), INTERVAL 21 HOUR))
which can then be used as the conditional on an outer SELECT.
I have a query that selects records created from 1 hour in past from current time.
select ts from <table_name> where ts >= DATE_SUB(NOW(), interval 1 hour);
I can also select date before 7 days using
select count(*) from <table_name> where ts >= DATE_SUB(NOW(), interval 7 day);
How can I use these two date features to get records before 7 days from today and time 1 hour in past from current time.
For example, if the present time is 2015-11-06 10:03:00 then how can I get data for time between 2015-10-30 09:03:00 to 2015-10-30 10:03:00
I tried something like this, but it gives syntax error:
select ts from <table_name> where ts >= DATE_SUB(DATE(NOW()), INTERVAL 7 DAY), interval 1 hour)
select ts from <table_name> where ts >= DATE_SUB(NOW(), INTERVAL 7 DAY), interval 1 hour)
Your examples have syntax errors (too many closing parentheses )). If you want to use DATE_SUB(), you need to use it twice. To get entries between one time and another, use WHERE ... BETWEEN ... AND ...
You can use this:
SELECT ts
FROM iv_split_skill_metrics
WHERE ts BETWEEN
DATE_SUB(
DATE_SUB(DATE(NOW()), INTERVAL 7 DAY),
interval 1 hour)
AND
DATE_SUB(DATE(NOW()), INTERVAL 7 DAY)
Or, even better, skip DATE_SUB() entirely and just do subtraction, like this:
SELECT ts
FROM iv_split_skill_metrics
WHERE ts BETWEEN NOW() - INTERVAL 7 DAY - INTERVAL 1 HOUR
AND NOW() - INTERVAL 7 DAY
Edit: For some reason, you edited your question after I posted this and replaced iv_split_skill_metrics with <table_name> in your question, but the examples above will work regardless. Just use the correct table and column names, of course!
Edit 2: I see now that you want entries between 7 days plus 1 hour ago and 7 days ago. I have tweaked my answer to show you how to do that.
Your goal is not 100% clear but just my attempt:
SELECT ts
FROM table_name
WHERE ts >= DATE_ADD(DATE_ADD(NOW(), INTERVAL -7 DAY), INTERVAL -1 HOUR)
AND ts <= DATE_ADD(NOW(), INTERVAL -7 DAY);
but form performance perspective this query would be much faster:
http://sqlfiddle.com/#!9/9edd1/2
SET #end = DATE_ADD(NOW(), INTERVAL -7 DAY);
SET #start = DATE_ADD(#end, INTERVAL -1 HOUR);
SELECT ts
FROM table_name
WHERE ts BETWEEN #start AND #end;
startTimestamp < date_sub(curdate(), interval 1 hour)
Will the (sub)query above return all records created within the hour? If not will someone please show me a correct one? The complete query may look as follows:
select * from table where startTimestamp < date_sub(curdate(), interval 1 hour);
Rather than CURDATE(), use NOW() and use >= rather than < since you want timestamps to be greater than the timestamp from one hour ago. CURDATE() returns only the date portion, where NOW() returns both date and time.
startTimestamp >= date_sub(NOW(), interval 1 hour)
For example, in my timezone it is 12:28
SELECT NOW(), date_sub(NOW(), interval 1 hour);
2011-09-13 12:28:53 2011-09-13 11:28:53
All together, what you need is:
select * from table where startTimestamp >= date_sub(NOW(), interval 1 hour);