Doing datetime math in a function call in an Oracle query - datetime

Ok, I got the first part of my question answered, so here's the second part. :-) In a PLSQL query, I have criteria that looks like this:
where Doc3.clinicalDate >= ml.convert_date_to_id(:DateBegin)
and Doc3.clinicalDate < ml.convert_date_to_id(:DateEnd)
Now, I don't want to use :DateEnd itself -- I want to add 1 day so that when it compares the datetime to midnight, I get midnight of the next day. Unfortunately, when I do
where Doc3.clinicalDate >= ml.convert_date_to_id(:DateBegin)
and Doc3.clinicalDate < ml.convert_date_to_id(:DateEnd + 1)
I get "ORA-06553: PLS-306: wrong number or types of arguments in call to 'CONVERT_DATE_TO_ID'". ":DateEnd + interval '1' day" gives me "ORA-30081: invalid data type for datetime/interval arithmetic" (where :DateEnd is bound to 31-MAY-2012). If I do "convert_date_to_id(add_months(:DateEnd, 1))", it works fine. Any thoughts? Thanks.
ETA: I should clarify that this is an SSRS 2008 R2 project, and DateBegin and DateEnd are defined in the report parameters as DateTime parameters. My current workaround involves setting the :DateEnd query parameter equal to the #DateEnd report parameter + 1, but I'm worried that someday I'll forget to document this properly and confuse the heck out of whomever's trying to maintain the report (and it might be me). I don't want to pass string parameters, as suggested before.

I'm thinking that the parameters being DateTime is root of the problem. Microsoft DateTime datatypes are way more granular than Oracle's in that it supports fractional seconds and Oracle DATE format does not (Oracle TIMESTAMP does however).
Since ADD_MONTHS just spits back whatever it's passed in DATE datatype (i.e. passed TIMESTAMP becomes DATE). So maybe you can convert the parameter and add the day that way:
where Doc3.clinicalDate >= ml.convert_date_to_id(:DateBegin)
and Doc3.clinicalDate < ml.convert_date_to_id(CAST(:DateEnd as DATE)+1)
Alternatively, forget about conversions and date arithmetic on the parameters and subtract a day from the second clinicalDate:
where Doc3.clinicalDate >= ml.convert_date_to_id(:DateBegin)
and Doc3.clinicalDate - 1 < ml.convert_date_to_id(:DateEnd)

Assuming that ml.convert_date_to_id takes a DATE as an input parameter rather than a VARCHAR2 that represents a date, and assuming that the :DateEnd bind variable is a VARCHAR2, you would need something like
ml.convert_date_to_id( to_date( :DateEnd, 'DD-MON-YYYY' ) + 1 )
or
ml.convert_date_to_id( to_date( :DateEnd, 'DD-MON-YYYY' ) + interval '1' day )

Use to_date to convert the value. For example:
select &date + 1 from dual
Informing to_date('29052012','ddmmyyyy') works fine
Informing '29-may-2012' gives ORA-01722: invalid number

Related

How do i subtract time from datetime in snowflake?

pdt.startTime is datetime
s_first.FromTimeOfDay is a time
I want to subtract the time drom the datetime. When i run the code below, Snowflake gives me this error invalid type [CAST(S_FIRST.FROMTIMEOFDAY AS TIMESTAMP_NTZ(9))] for parameter 'TO_TIMESTAMP_NTZ'
select (pdt.StartTime - (SELECT s_first.FromTimeOfDay::datetime FROM Shift s_first))
from RAW_CPMS_AAR.POWERBI_DowntimeTable AS PDT
When i try this:
select (pdt.StartTime::TIMESTAMP_NTZ(9) - (SELECT s_first.FromTimeOfDay::TIMESTAMP_NTZ(9) FROM Shift s_first))
from RAW_CPMS_AAR.POWERBI_DowntimeTable AS PDT
I get more or less the same error: invalid type [CAST(S_FIRST.FROMTIMEOFDAY AS TIMESTAMP_NTZ(9))] for parameter 'TO_TIMESTAMP_NTZ'
How do I convert the time into a datetime format so that I can subtract the two. It doesnt seem to me that there is a clear way to convert time into datetime in snowflake.
Is this what you're after?
select current_timestamp() as sample_timestamp
, time(sample_timestamp) as sample_time
, date(sample_timestamp) as sample_date;
A user pointed me in the right direction. i didnt realize i could use "dateadd" to also subtract time.
dateadd(HOUR, - (HOUR(current_timestamp())), temp.DateTime)

Checking if a Date falls within a Range of Dates in SQLITE

I have an sqlite table with with 2 date columns (beginning & end). I am looking for a query that returns the date range a date falls in. e.g Checking range where 10-02-2016 falls given 2 records as follows
(01-02-2016 - 12-02-2016) & (13-02-2016 - 20-02-2016)
Clearly it falls in the first range but how do I do it in SQLITE. Please help?
I think the problem is next SQLite requires dates to be in format YYYY-MM-DD. With that format you could write a simple query:
select * from table where yourdate between begin and end
If you can't change your format you should look at next sqlite functions https://sqlite.org/lang_datefunc.html
Also you can try substr function to cotact date in needed format.

In Cognos 10.2.1 - how can I use substring portions of an input parameter to create an expression to use for date comparison?

In Cognos 10.2.1 (FP7), I have a situation with two tables (see below), where a given transaction may be in the same "PERIOD", but what I want to do is to only give me results for transactions that have a date after the 15th of the month (i.e - the transaction may be in PERIOD 201510, and I only want transactons on/after 10/15/2015). The PERIOD is an input parameter that the user selects - I want to build the date from a portion of the PERIOD. (Before anyone complains about syntax, etc. - I've tried to simplify this as much as possible).
Given Table A:
ID varchar
PERIOD varchar
Given Table B:
ID varchar
TYPE varchar
TRANDATE timestamp2
Query1
[A.PERIOD]=?PARM1? <- this is the user selected input parameter
Query2
[B.TYPE] in ('A','B')
Then create a join from the results of Query1 and Query2 on the A.ID=B.ID to give Results1
I've tried the following (I'm keeping this as simple as I can - so I'm ONLY working with the YEAR portion of the period):
[Results1].[TRANDATE] >= concat(substring([Results1].[PERIOD],1,4),'-10-15T00:00:00.000000000')
[Results1].[TRANDATE] >= cast(concat(substring([Results1].[PERIOD],1,4),'-10-15T00:00:00.000000000'), timestamp2)
In both cases - Cognos won't validate the expression, or, if it does validate, I get a runtime error when running the report. In both cases, I get messages basically "literal does not match format string", even with the cast.
So - how can I get pieces/portions of the parameter, and slice/dice them to use as a date comparison as I mentioned above?
Given: Column [PERIOD] of type integer in the form YYYYMM, [TRANDATE] of type date/time
[TRANDATE] >= cast(cast(cast([PERIOD]/100,integer),varchar(4)) || '-' || cast(mod([PERIOD],100),varchar(2)) || '-15',date)
Given: Column [PERIOD] of type string in the form 'YYYYMM', [TRANDATE] of type date/time
[TRANDATE] >= cast(substring([PERIOD],1,4) || '-' || substring([PERIOD],5,2) || '-15',date)
The trick is that you don't have to build a full date/time string. You only have to build a string of format 'YYYY-MM-DD' in order to cast to a date type.

What format is the Safari History.db history_visits.visit_time in?

When looking at the History.db from Safari, there's a table named history_visits which has a column named visit_time, which is a REAL value. It has values such as 470799793.096987. What format is that in? I'd like to see it in a format such as 12/08/2015 05:12:05.
It's the number in seconds since 00:00:00 UTC on 1 January 2001. It must be coming from an NSDate.
NSDate objects encapsulate a single point in time, independent of any particular calendrical system or time zone. Date objects are immutable, representing an invariant time interval relative to an absolute reference date (00:00:00 UTC on 1 January 2001).
— NSDate Class Reference
To get a decent human value out of it, you must add 978307200 (the epoch for 2001-01-01 00:00:00).
This query should give you what you want:
.headers on
select datetime(v.visit_time + 978307200, 'unixepoch', 'localtime') as date, v.visit_time + 978307200 as epoch, v.visit_time, i.domain_expansion, i.url
from history_items i left join history_visits v on i.id = v.history_item
order by i.id desc
limit 100;
Example output:
date|epoch|visit_time|domain_expansion|url
2015-12-31 11:51:27|1451562687.28465|473255487.284646|duckduckgo|https://duckduckgo.com/?q=current+timestamp+2015-12-31+11:51&t=osx
PS: Just for future reference, the Safari db file is located at ~/Library/Safari/History.db
To convert the visit_time value in the history.db in an excel spread sheet, open the history.db file in a tool such as DB browser for SQLLite (Windows) and export the history_visits values to a CSV file.
Open the CSV file and create a column where you will populate your values in human readable time adjusted to your time zone, and use the following formula convert your NSDate:
=((((C2+978307200)/60)/60)/24)+DATE(1970,1,1)+(-5/24)
In the above formula, the time value is in cell C2, and my time zone GMT-5. To adjust to your own time zone adjust the statement in the last set of parenthesis. Presently I have (-5/24) to represent GMT-5.
When I first approached this conversion, I mistakenly assumed the time in the history.db to be epoch time, which starts at 1/1/1970, and did not understand why there was such a skew in time. Adding the required conversion factor +978307200 solved the problem.
I found the domain_expansion field to be null in some cases, here's a modified query:
SELECT SUBSTR(
SUBSTR(url, INSTR(url, '/')+2),
1,
INSTR(SUBSTR(url, INSTR(url, '/')+2),'/') - 1
) domain,
url,
datetime(hv.visit_time + 978307200, 'unixepoch', 'localtime') visit_time
FROM history_items hi
JOIN history_visits hv on hi.id = hv.history_item;

I need a sqlite equivalent of the folling msaccess query

Select distinct Format(DateAdd(""s""," & columnname & ",""1/1/1980 12:00:00 AM""), 'dd-MMM-yyyy') as A
I have assumed that the seconds to add and the original date are hard coded values below whilst awaiting clarifications requested in the comments.
To add a number of seconds to a date you can use:
select datetime('1980-01-01 00:00:00', "345000 seconds");
This gives the result: 1980-01-04 23:50:00
The example above is just under 4 days in seconds, if you want to truncate the result to just the date as implied by the query in your questions then you can wrap this inside a date function. However, this would give the result in the format "YYYY-MM-DD" rather than "DD-MMM-YYYY" as your access query does.
Unfortunately I cannot find any native SQLite function to convert a numeric month value to mmm format. You can do this manually with replace (similar to the answer to this question), but this is a bit messy.
If you are happy to live with the numeric months then you can simply use:
select strftime('%d-%m-%Y', '1980-01-01 00:00:00', "345000 seconds");
This gives the result: 04-01-1980
More information on the SQLite date / time functions can be found here.

Resources