I am confused by the nature of logical operators upon datetime data in sql.
In my database's table RecordDateTime is saved like:
2014-04-09 15:28:32.000
I am retrieving on basis of this query:
select
*
from [GPSDB].[dbo].[Coordinates]
where IMEI= '354400055967495'
and RecordedDateTime >= '2014-04-09 15:28:32.000'
and RecordedDateTime <= '2014-04-09 15:39:20.000'
Now it returns 4 rows which falls between these both dates range or equal as expected but confusion starts from here when i remove Seconds part from first date then still it works and returns same result set i.e.
select
*
from [GPSDB].[dbo].[Coordinates]
where IMEI = '354400055967495'
and RecordedDateTime >= '2014-04-09 15:28'
and RecordedDateTime <= '2014-04-09 15:39:20.000'
but if i remove seconds part from 2nd date then it returns only one row with matching time of first date being provided. Weird ? :/
Help Please.
the datetime data 2014-04-09 15:28:32.000 have two part date part 2014-04-09 and time part 15:28:32.000.
So when you say
RecordedDateTime >= '2014-04-09 15:28:32.000' and RecordedDateTime <= '2014-04-09 15:39:20.000'
It will consider the time part as well and since there is 11 minutes gap between; it will fetch you all those record which falls in that range.
But when you say below, it will consider only the date part for comparison and there is only 1 day and hence it will fetch the first record of that date 2014-04-09
RecordedDateTime >= '2014-04-09'
and RecordedDateTime <= '2014-04-09'
Related
I am running the below query to get data recorded in the past 24 hours. I need the same data recorded starting midnight (DATE > 12:00 AM) and also data recorded starting beginning of the month. Not sure if using between will work or if there is better option. Any suggestions.
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CNLD'
AND
TRUNC(TO_DATE('1970-01-01','YYYY-MM-DD') + OPEN_DATE/86400) = trunc(sysdate)
Output (Just need Count). OPEN_DATE Data Type is NUMBER. the output below displays count in last 24 hours. I need the count beginning midnight and another count starting beginning of the month.
The query you've shown will get the count of rows where OPEN_DATE is an 'epoch date' number representing time after midnight this morning*. The condition:
TRUNC(TO_DATE('1970-01-01','YYYY-MM-DD') + OPEN_DATE/86400) = trunc(sysdate)
requires every OPEN_DATE value in your table (or at least all those for CNLD rows) to be converted from a number to an actual date, which is going to be doing a lot more work than necessary, and would stop a standard index against that column being used. It could be rewritten as:
OPEN_DATE >= (trunc(sysdate) - date '1970-01-01') * 86400
which converts midnight this morning to its epoch equivalent, once, and compares all the numbers against that value; using an index if there is one and the optimiser thinks it's appropriate.
To get everything since the start of the month you could just change the default behaviour of trunc(), which is to truncate to the 'DD' element, to truncate to the start of the month instead:
OPEN_DATE >= (trunc(sysdate, 'MM') - date '1970-01-01') * 86400
And the the last 24 hours, subtract a day from the current time instead of truncating it:
OPEN_DATE >= ((sysdate - 1) - date '1970-01-01') * 86400
db<>fiddle with some made-up data to get 72 back for today, more for the last 24 hours, and more still for the whole month.
Based on your current query I'm assuming there won't be any future-dated values, so you don't need to worry about an upper bound for any of these.
*Ignoring leap seconds...
It sounds like you have a column that is of data type TIMESTAMP and you only want to select rows where that TIMESTAMP indicates that it is today's date? And as a related problem, you want to find those that are the current month, based on some system values like CURRENT TIMESTAMP and CURRENT DATE? If so, let's call your column TRANSACTION_TIMESTAMP instead of (reserved word) DATE. Your first query could be:
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CLND'
AND
DATE(TRANSACTION_TIMESTAMP)=CURRENT DATE
The second example of finding all for the current month up to today's date could be:
SELECT COUNT(NUM)
FROM TABLE
WHERE
STATUS = 'CLND'
AND
YEAR(DATE(TRANSACTION_TIMESTAMP)=YEAR(CURRENT DATE) AND
MONTH(DATE(TRANSACTION_TIMESTAMP)=MONTH(CURRENT DATE) AND
DAY(DATE(TRANSACTION_TIMESTAMP)<=DAY(CURRENT DATE)
I have an Informix database (over which I have no control other than executing SELECT statements) which contains the following columns:
Date | Time | Column1 | Column2 | Column3
Date is a date/time format, Time is an integer (storing, for example 8am as 800 and 1pm as 1300). The other columns are irrelevant for this purpose but let's say they are integers which I want to SUM.
What's the most efficient way I can SUM my columns Column1, Column2, and Column3? Let's say I want rows between 10am on August 1st 2019, and 11am on August 5th 2019.
My first attempt was:
SELECT Date, Time, SUM(Column1), SUM(Column2), SUM(Column3)
FROM table
WHERE (Date >= '08/01/19' AND Time >= 1000) AND (Date <= '08/05/19' AND Time < 1100);
But just thinking through the logic of that means I'm simultaneously asking for something to be >=1000 and < 1100. The result was only records between 10am and 11am on those days were returned.
My next attempt was:
SELECT Date, Time, SUM(Column1), SUM(Column2), SUM(Column3)
FROM table
WHERE ((Date = '08/01/19' AND Time >= 1000)
OR (Date BETWEEN '08/02/19' AND '08/04/19')
OR (Date = '08/05/19' AND Time < 1100));
This provides the result I'm looking for but doesn't seem very efficient - and potentially complex to construct programmatically.
If this is the best solution, I'm ok with that. Just hoping for someone smarter than me to put me right.
If you are storing the values in different columns, then you seem to want:
where (date > '2019-08-01' or
date = '2019-08-01' and time > 1000
) and
(date < '2019-08-05' or
date = '2019-08-05' and time < 1100
)
This would be simpler if the date/time values were stored in a single column.
I want to write a SQL query in Oracle database for:
A priceindex(field name) have around 120(say) records each day and I have to display the priceindex name and today's date, if the avg of last 7 days record count is greater than Todays record count for the priceindex(group by priceindex).
Basically, There will be 56 priceindex and each should have around 120 records each day and is dump to database each day from external site. So want to make sure all records are downloaded to the database everyday.
Except for the clarification I requested in a Comment to your question (having to do with "how can we know today's final count, when today is not over yet), the problem can be solved along the following lines. Not tested since you didn't provide sample data.
From your table, select only the rows where the relevant DATE is between "today" - 7 and "today" (so there are really EIGHT days: the seven days preceding today, and today). Then group by PRICEINDEX. Count total rows for each group, and count rows just for "today". The rows for "today" should be less than 1/8 times the total count (this is easy algebra: this is equivalent to being less than 1/7 times the count of OTHER days).
Such conditions, at the group level, must be in the HAVING clause.
select priceindex
from your_table
where datefield >= trunc(sysdate) - 7 and datefield < trunc(sysdate) + 1
group by priceindex
having count(case when datefield >= trunc(sysdate) then 1 end) < 1/8 * count(*)
;
EDIT The OP clarified that the query runs every day at midnight; this means that "today" should actually mean "yesterday" (the day that just ended). In Oracle, and probably in all of computing, midnight belongs to the day that BEGINS at midnight, not the one that ends at midnight. The time-of-day at midnight is 00:00:00 (beginning of the new day), not 24:00:00.
So, the query above will have to be changed slightly:
select priceindex
from your_table
where datefield >= trunc(sysdate) - 8 and datefield < trunc(sysdate)
group by priceindex
having count(case when datefield >= trunc(sysdate) - 1 then 1 end)
< 1/8 * count(*)
;
I'm trying to retrieve data for a specific date with query:
Select * from table_1 where activity_date = to_date('13-09-2017','DD-MM-YYYY');
But I'm not getting any result.
But when I query below:
Select * from table_1 where activity_date >= to_date('13-09-2017','DD-MM-YYYY');
I'm getting the data for days greater than equal to 13-09-2017.
Any help?
It seems the data type of your column is Date Time and hence when you are querying with just date (13-09-2017), it searching for date as well as time (13-09-2017 00:00:00). Seems there are no record in your database with this exact date time stamp and hence no results are being returned. Below query will work in your case:
SELECT *
FROM table_1
WHERE activity_date >= to_date('13-09-2017','DD-MM-YYYY')
AND activity_date < to_date('14-09-2017','DD-MM-YYYY');
When you compare dates remember that you usually compare some kind of a timestamp. A timestamp usually also has hours, minutes, seconds etc. So in your database you probably have a whole timestamp like '13-09-2017' + specific hour, minutes and so on, whilst to_date explicitly only formats your DD MM and YYYY causing the hour, minutes and seconds to be equal to 0. The query is probably not returning any records as you probably don't have a date with the exact time equal to 00:00:00.
That's also why a comparison like >= will return results. Because your '13-09-2017' database entries are all greater than '13-09-2017' (with hour equal to 00:00:00) because they all have some hours, minutes and seconds to them, for e.g 13-09-2017 04:02:45 which is greater than 13-09-2017 00:00:00).
How to solve this? Well for example:
SELECT *
FROM table_1
WHERE activity_date >= to_date('13-09-2017','DD-MM-YYYY')
AND activity_date < to_date('14-09-2017','DD-MM-YYYY')
I need to get the number of records present in my [RecordsTable] for the last 3 months.
However the catch is I need the records which are processed between 10PM and 2AM.
For example --
07/01/2015 10PM -- 07/02/2015 2AM
07/02/2015 10PM -- 07/03/2015 2AM
07/03/2015 10PM -- 07/04/2015 2AM
The below SQL gives me the records present on any particular day starting from May,2015.
But I am not able to get the timing(10PM-2AM of next day) embedded in the SQL and need some help.
SELECT CONVERT(VARCHAR(12), RecordDate, 101),count(RecordID)
FROM [RecordsTable](NOLOCK)
WHERE RecordDate > '2015-05-01'
GROUP BY CONVERT(VARCHAR(12), RecordDate, 101)
MSSQL Supports both Date and Time datatypes. You can break up your where statement to reflect both date and time conditions separately.
SELECT COUNT(Records)
FROM TABLE
WHERE CONVERT(Date,DateCol) BETWEEN 'MM/DD/YYYY' AND 'MM/DD/YYYY'
AND CONVERT(Time,DateCol) BETWEEN 'HH:MM:SS' AND 'HH:MM:SS'
Try the following:
SELECT count(1)
FROM RecordsTable
WHERE RecordDate > '2015-05-01'
AND NOT DATEPART(hour, RecordDate) BETWEEN 2 AND 21
I assume RecordDate is a datetime or datetime2 column. between 2 and 21 will return rows where the hour for RecordDate is between 2am and 9pm, inclusive. NOT between 2 and 21 will return the reverse, giving you data for 10pm, 11pm, 12pm, and 1am. This does not include any time between 2:00am and 2:59am. If you need to include events that occurred precisely at but not after 2:00am, things get a bit tricker, but similar code based on not between would apply.
To get records in the last 3 months you can use two ways -- one by month looks like this
WHERE MONTH(colname) >= MONTH(GETDATE()) -3
This will get you inclusive months but not partial months. To get partial months is a bit more tricky because you could mean (for example for today) the 9th day of 3 months ago or you could mean 90 days ago. In the first case this works
WHERE colname >= dateadd(month,-3, getdate())
and for 90 days ago
WHERE colname >= dateadd(day,-90, getdate())
To get between 10PM and 2AM use this
WHERE datepart(hour,colname) >= 22 OR datepart(hour,colname) <= 2
Use DATEPART
SELECT COUNT(1)
FROM Table1
WHERE RecordDate > '2015-05-01'
AND (DATEPART(HOUR, RecordDate) <= 2 OR DATEPART(HOUR, RecordDate) >= 22)
Try this
SELECT count(*) FROM tablename where created_at>='2015-03-17 07:15:10' and created_at<='2015-07-09 02:23:50';
You can even use between
SELECT count(*) FROM tablename where created_at between '2015-03-17 07:15:10' and '2015-07-09 02:26:50';
You can use curdate() to get today's date