SQL Select within a range of seconds - sql

I have the table below
2012-05-24 19:00:00.000
2012-07-27 15:51:18.750
2012-07-30 09:40:25.333
2012-07-30 14:25:27.563
2012-07-27 15:51:18.750
2012-07-30 09:40:25.333
2012-07-30 14:25:27.563
2012-05-12 09:23:16.850
2012-05-12 18:00:00.000
I am trying to do a range select, so for example
SELECT * FROM RUN WHERE RUN_DATETIME = '14:25:29.563'
This is a very simple select, but my problem is that the date I am searching code be up too 30 seconds out from what is in the table above, so I need to be able to do the same as above but with a 30 second window and I am not sure what the best way to do this is.
This select is not based on another row, just the rows RUN_DATE within the window.
I am using SQL server 2008 R2

SELECT * FROM RUN
WHERE RUN_DATETIME < DATEDADD(s, '14:25:29.563', 30) AND
RUN_DATETIME > DATEDADD(s, '14:25:29.563', -30)
More complicated looking than podiluska's answer, but this works with indexes by pre-calculating the range.

SELECT *
FROM RUN
WHERE ABS(DATEDIFF(s, RUN_DATETIME , '14:25:29.563' ))< 30

SELECT
*
FROM
RUN
WHERE
RUN_DATETIME >= DATEADD(second, -30, '14:25:29.563')
AND RUN_DATETIME < DATEADD(second, 30, '14:25:29.563')
This is longer than the ABS(DATEDIFF()) version. It is, however, much faster when applied to indexed fields.
That is because the optimiser can easily see that you want all records within one sequential block. It can search for the start, then search for the end, and return everything between.
The ABS(DATEDIFF()) variation requires every row to be checked independantly, and makes no use of indexes or range seeks. It's a full scan of the whole table.
EDIT:
Also note that I use >= and <. This is standard practice for ranges of time.
For example val >= 0 AND val < 60 and val >= 60 AND val < 120 ensures that the value at val = 60 is only counted in one range of time.

I think RUN_DateTime column contains Date and comparison we are doing is with only Time here '14:25:29.563'. I agree with podiluska's answer. Just we would need to convert '14:25:29.563' to a date by taking out Day, month, year from RUN_DateTime column. We can do it by Date_Part function.

Related

SQL Getting data by the hour

Hi I have a weather database in SQL Server 2008 that is filled with weather observations that are taken every 20 minutes. I want to get the weather records for each hour not every 20 minutes how can I filter out some the results so only the first observation for each hour is in the results.
Example:
7:00:00
7:20:00
7:40:00
8:00:00
Desired Output
7:00:00
8:00:00
To get exactly (less the fact that it's an INT instead of a TIME; nothing hard to fix) what you listed as your desired result,
SELECT DISTINCT DATEPART(HOUR, TimeStamp)
FROM Observations
You could also add in CAST(TimeStamp AS DATE) if you wanted that as well.
Assuming you want the data as well, however, it depends a little, but from exactly what you've described, the simple solution is just to say:
SELECT *
FROM Observations
WHERE DATEPART(MINUTE, TimeStamp) = 0
That fails if you have missing data, though, which is pretty common.
If you do have some hours where you want data but don't have a row at :00, you could do something like this:
WITH cte AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY CAST(TimeStamp AS DATE), DATEPART(HOUR, TimeStamp) ORDER BY TimeStamp)
FROM Observations
)
SELECT *
FROM cte
WHERE n = 1
That'll take the first one for any date/hour combination.
Of course, you're still leaving out anything where you had no data for an entire hour. That would require a numbers table, if you even want to return those instances.
You can use a formula like the following one to get the nearest hour of a time point (in this case it's GETUTCDATE()).
SELECT DATEADD(MINUTE, DATEDIFF(MINUTE, 0, GETUTCDATE()) / 60 * 60, 0)
Then you can use this formula in the WHERE clause of your SQL query to get the data you want.
What you need is to GROUP BY your desired time frame, like the date and the hours. Then, you get the MIN value of the timeframe. Since you didn't specify which columns you are using, this is the most generic thing i can give.
Use as filter :
... where DATEPART(MINUTE, DateColumn) = 0
To filter the result for every whole hour, you can set your where clause to check for 00 minute since every whole hour is HH:00:00.
To get the minute part from a time-stamp, you can use DATEPART function.
SELECT *
FROM YOURTABLENAME
WHERE DATEPART(MINUTE, YOURDATEFIELDNAME) = 0
More information on datepart function can be found here: http://www.w3schools.com/sql/func_datepart.asp

Giving the wrong records when used datetime parameter in MS Access Query

I am working MS-Access 2007 DB .
I am trying to write the query for the Datetime, I want to get records between 14 December and 16 December so I write the bellow query.
SELECT * FROM Expense WHERE CreatedDate > #14-Dec-15# and CreatedDate < #16-Dec-15#
( I have to use the two dates for the query.)
But It returning the records having CreatedDate is 14 December...
Whats wrong with the query ?
As #vkp mentions in the comments, there is a time part to a date as well. If it is not defined it defaults to midnight (00:00:00). As 14-dec-2015 6:46:56 is after 14-dec-2015 00:00:00 it is included in the result set. You can use >= 15-dec-15 to get around this, as it will also include records from 15-dec-2015. Same goes for the end date.
It seems you want only records from Dec 15th regardless of the time of day stored in CreatedDate. If so, this query should give you what you want with excellent performance assuming an index on CreatedDate ...
SELECT *
FROM Expense
WHERE CreatedDate >= #2015-12-15# and CreatedDate < #2015-12-16#;
Beware of applying functions to your target field in the WHERE criterion ... such as CDATE(INT(CreatedDate)). Although logically correct, it would force a full table scan. That might not be a problem if your Expense table contains only a few rows. But for a huge table, you really should try to avoid a full table scan.
You must inlcude the time in your thinking:
EDIT: I wrote this with the misunderstanding, that you wanted to
include data rows from 14th to 16th of Dec (three full days).
If you'd write <#17-Dec-15# it would be the full 16th. Or you'd have to write <=#16-Dec-15 23:59:59#.
A DateTime on the 16th of December with a TimePart of let's say 12:30 is bigger than #16-Dec-15#...
Just some backgorund: In Ms-Access a DateTime is stored as a day's number and a fraction part for the time. 0.5 is midday, 0.25 is 6 in the morning...
Comparing DateTime values means to compare Double-values in reality.
Just add one day to your end date and exclude this:
SELECT * FROM Expense WHERE CreatedDate >= #2015/12/14# AND CreatedDate < #2015/12/17#
Thanks A Lot guys for your help...
I finally ended with the solution given by Darren Bartrup-Cook and Gustav ....
My previous query was....
SELECT * FROM Expense WHERE CreatedDate > #14-Dec-15# and CreatedDate < #16-Dec-15#
And the New working query is...
SELECT * FROM Expense WHERE CDATE(INT(CreatedDate)) > #14-Dec-15# and CDATE(INT(CreatedDate)) < #16-Dec-15#

Get data that is no more than an hour old in BigQuery

Trying to use the statement:
SELECT *
FROM data.example
WHERE TIMESTAMP(timeCollected) < DATE_ADD(USEC_TO_TIMESTAMP(NOW()), 60, 'MINUTE')
to get data from my bigquery data. It seems to return same set of result even when time is not within the range. timeCollected is of the format 2015-10-29 16:05:06.
I'm trying to build a query that is meant to return is data that is not older than an hour. So data collected within the last hour should be returned, the rest should be ignored.
Using Standard SQL:
SELECT * FROM data
WHERE timestamp > TIMESTAMP_ADD(CURRENT_TIMESTAMP(), INTERVAL -60 MINUTE)
The query you made means "return to me anything that has a collection time smaller than an hour in the future" which will literally mean your whole table. You want the following (from what I got through your comment, at least) :
SELECT *
FROM data.example
WHERE TIMESTAMP(timeCollected) > DATE_ADD(USEC_TO_TIMESTAMP(NOW()), -60, 'MINUTE')
This means that any timeCollected that is NOT greater than an hour ago will not be returned. I believe this is what you want.
Also, unless you need it, Select * is not ideal in BigQuery. Since the data is saved by column, you can save money by selecting only what you need down the line. I don't know your use case, so * may be warranted though
To get table data collected within the last hour:
SELECT * FROM [data.example#-3600000--1]
https://cloud.google.com/bigquery/table-decorators
Using Standard SQL:
SELECT * FROM data WHERE timestamp > **TIMESTAMP_SUB**(CURRENT_TIMESTAMP(), INTERVAL 60 MINUTE)

SQL to filter for records more than 30 days old

Suppose I have the following query:
select customer_name, origination_date
where origination_date < '01-DEC-2013';
I would like to select all customers that have an origination date older than 30 days. Is there a way in SQL (oracle, if specifics needed) to specify it in a more dynamic approach than manually entering the date so that I don't need to update the query every time I run it?
Thanks!
Sure try something like this:
select customer_name, origination_date where
origination_date >= DATEADD(day, -30, GETUTCDATE());
This basically says where the origination_date is greater or equal to 30 days from now. This works in Microsoft SQL, not sure but there is probably a similar function on Oracle.
in Oracle, when you subtract dates, by default you get the difference in days, e.g.
select * from my_table where (date_1 - date_2) > 30
should return the records whose date difference is greater than 30 days.
To make your query dynamic, you parameterize it, so instead of using hard coded date values, you use:
select * from my_table where (:date_1 - :date_2) > :threshold
If you are using oracle sql developer to run such a query, it will pop up a window for you to specify the values for your paramteres; the ones preceded with colon.

SQL: Difference between "BETWEEN" vs "current_date - number"

I am wondering which of the following is the best way to implement and why.
select * from table1 where request_time between '01/18/2012' and '02/17/2012'
and
select * from table1 where request_time > current_date - 30
I ran the two queries through some of my date tables in my database and using EXPLAIN ANALYZE I found these results:
explain analyze
select * from capone.dim_date where date between '01/18/2012' and '02/17/2012'
Total runtime: 22.716 ms
explain analyze
select * from capone.dim_date where date > current_date - 30
Total runtime: 65.044 ms
So it looks like the 1st option is more optimal. Of course this is biased towards my DBMS but these are still the results I got.
The table has dates ranging from 1900 to 2099 so it is rather large, and not just some dinky little table.
Between has the inclusive ranges i.e when you issue a query like id between 2 and 10 the value of 2 and 10 will also be fetched.If you want to eliminate these values use > and <.
Also when indexes are applied say on date column > and < makes a good use of index than between.