Calculations on dynamic date variable - sql

Im using Oracle SQL platform and Im using a variable #Quarter to prompt for a Quarter and related data that I want to see. This variable is based on a column that has a format "YYYY QQ" (for example "2018 Q2").
Now Its really easy to pass that variable but how can I add a time to this variable to get a next or previous quarter?
I tried: TIMESTAMPADD(SQL_TSI_QUARTER, -1, #QUARTER')
and the sql issued looked like:
(TIMESTAMPADD(SQL_TSI_QUARTER, -1, '2017 Q 4')
unfortunately my variable doesnt have appropriate format, its just "2017 Q 4" so not a timestamp...
I also tried: TIMESTAMPADD(SQL_TSI_QUARTER, -1, CAST('#QUARTER' AS DATE))
and the sql issued looked:
(TIMESTAMPADD(SQL_TSI_QUARTER, -1, CAST('2017 Q 4' AS DATE)))
like it didnt even recognize the function CAST inside...
Is there anything I can do to make a calculations on that variable?
Many Thanks,
Alex

You can cut up your input with substr and get it into a date format within the Quarter's range. Then you'll just need to add quarters (shown as quarters * 3 months: -1 * 3 and 1 * 3 in my example) to get those before/after.
with x as (select '2017 Q4' as input from dual)
select input,
to_date(substr(input,1,4) || '-' || substr(input,7,1) * 3, 'yyyy-mm') as in_date_format,
to_char(add_months(to_date(substr(input,1,4) || '-' || substr(input,7,1) * 3, 'yyyy-mm'), -1 * 3), 'yyyy "Q"q') as last_quarter,
to_char(add_months(to_date(substr(input,1,4) || '-' || substr(input,7,1) * 3, 'yyyy-mm'), 1 * 3), 'yyyy "Q"q') as next_quarter
from x;
Without seeing your code, this is the best I could do to represent what I am talking about...

Related

SQLlite functions on date format YYYY-MM-DDTHH:MM:SS.SSS+0000

select
datetime(SVMXC__Scheduled_Date_Time__c),
SVMXC__Scheduled_Date_Time__c
from table_a
Return a null for the datetime function.
I would like to get the difference between
datetime(SVMXC__Scheduled_Date_Time__c) - datetime('now')
2020-04-26T17:45:00.000+0000 is the date stored as a varchar.
For this to work, you need your date to have a format that SQLite recognizes. Here are two options.
If the offset is always +0000, as shown in the question, then you can just remove it. This gives you format YYYY-MM-DDTHH:MM:SS.SSS, which SQLite understands:
substr(SVMXC__Scheduled_Date_Time__c, 1, 23)
With this value at hand, you can then use julianday() to compute the difference to now, as a number of days:
select
SVMXC__Scheduled_Date_Time__c,
julianday(substr(SVMXC__Scheduled_Date_Time__c, 1, 23)) - julianday('now') diff
from mytable
--
On the other hand, if you do need to take the offset into account, then SQLite expects : between hours and minute, so you need to insert it in the string:
substr(SVMXC__Scheduled_Date_Time__c, 1, 25)
|| ':'
|| substr(SVMXC__Scheduled_Date_Time__c, 1, -2)
Then:
select
SVMXC__Scheduled_Date_Time__c,
julianday(
substr(SVMXC__Scheduled_Date_Time__c, 1, 25)
|| ':'
|| substr(SVMXC__Scheduled_Date_Time__c, 1, -2)
) - julianday('now') diff
from mytable

How can I adjust the Snowflake function to get date with error that it cannot parse?

I'm trying to convert numbers in this format 1180106 to dates.
I've been able to run the following query to get a YYYYMMDD format until today:
TO_DATE(1900 + LEFT(A.ODT_ENTERED_DATE, 3) || SUBSTR(A.ODT_ENTERED_DATE, 4, 4), 'YYYYMMDD')
The inner query builds a number like this: 2018.000000106
But then the TO_DATE function cannot create a date from it. I'm expecting 20180106
Instead I get the following error:
Can't parse '2018.000000106' as date with format 'YYYYMMDD'
If you just run:
select 1900 + LEFT(A.ODT_ENTERED_DATE, 3)
this returns the result as a varchar where the result returned is: 2018.00000
Cast to number in either of the following ways should give you the expected result :
select TO_DATE(1900 + TO_NUMBER(LEFT(1180106, 3))|| SUBSTR(1180106, 4, 4), 'YYYYMMDD')
or
SELECT TO_DATE((1900 + (LEFT(1180106, 3))) :: number || SUBSTR(1180106, 4, 4), 'YYYYMMDD')

query to search dates which are stored as string in the database

I have a table where I store an activity completion date as varchar. The format of the date stored is MM/DD/YYYY HH:MM:SS.
I have search window where I have two fields Completion date from and completion date to.The date format selected here is MM/DD/YYYY.
How do I write a query such that I am able to fetch the activity completion between two given dates from the table which has the dates stores as varchar.This table was created a long time back and no thought was given to saving dates as datetime.
You can use SQL CONVERT to change your columns to DATE format but that will cause performance issues.
SELECT *
FROM MyTable
WHERE CONVERT(DATETIME, MyDate) >= CONVERT(DATE, '01/01/2014')
AND CONVERT(DATETIME, MyDate) <= CONVERT(DATE, '01/31/2014')
CONVERT documentation - http://msdn.microsoft.com/en-us/library/ms187928.aspx
if you are unable to change how data is stored, than for better performance , you can create view with calculated column that converts VARCHAR to DATETIME. After that can create index on calculated column. Index on Computed Column documentation
Use the SUBSTRING function to get the date parts in a comparable order (i.e. yyyymmdd):
select *
from mytable
where
CONCAT( SUBSTRING(thedate, 7, 4) , SUBSTRING(thedate, 4, 2) , SUBSTRING(thedate, 1, 2) )
between
CONCAT( SUBSTRING(#FROMDATE, 7, 4) , SUBSTRING(#FROMDATE, 4, 2) , SUBSTRING(#FROMDATE, 1, 2) )
and
CONCAT( SUBSTRING(#TODATE, 7, 4) , SUBSTRING(#TODATE, 4, 2) , SUBSTRING(#TODATE, 1, 2) )
;
You could use this code :
select * from table_name
where CAST(col1 as date )
between CAST(Completion date from as date )
and CAST(Completion date to as date);
Function syntax CAST:
CAST ( expression AS data_type )
You can use below if the date format is {yyyy-MM-dd}, or you can adjust the charindex's index value depending on format
SELECT *
FROM table
WHERE
CHARINDEX('-', col_value, 0) = 5
AND CHARINDEX('-', col_value, 6) = 8
AND LEN(col_value) = 10
The above piece will look for first occurrence of char '-' at position 5 and the second char '-' at position 8 while the entire date value's length is equal to 10 chars
This is not full proof, but will narrow down the search. If you want to add time then just expand the criteria in the where to accommodate the format i.e. {yyyy-MM-dd 00:00:00.000}
This is a safe way to query the data, without any unexpected 'invalid cast / convert' errors.

update date value in oracle

I need to convert date format in ORACLE SQL Developer
The current format is yyyy/mm/dd-hh:mm:ss:sss and I need to convert it to yyyy-mm-dd hh:mm:ss CST
I don't really know SQL but did some research.
Here is the command that I consultanted other people on the forum. but it throws me unrecognized command error. table name is B and column name is First
UPDATAE B
set First = concat(to_char(substring(FIRST,1,4) + '-' + substring(FIRST, 6, 2) + '-' + substring(FIRST, 9, 2) + ' ' + substring(FIRST, 12, 8));
Could anyone here help me with it? thanks in advance.
The "unrecognized command" is merely a misspelling of UPDATE:
UPDATAE B
// Should be
UPDATE B
To verify the result is what you expect before executing the UPDATE statement, use a SELECT:
SELECT
to_char(substr(FIRST,1,4) || '-' || substr(FIRST, 6, 2) || '-' || substr(FIRST, 9, 2) || ' ' || substr(FIRST, 12, 8)) AS Test
FROM B
Umm... I'm either missing something extremely obvious or everyone else is.
You want to date operations? Use to_date and to_char. I'm going to assume this ss:sss means, seconds, then fractional seconds. You date appears to be a string so we need to convert it twice:
update b
set first = to_char( to_date( my_date, 'yyyy/mm/dd-hh:mi:ss:ff3')
,'yyyy-mm-dd hh:mi:ss' )
Generally, when using dates it's far, far easier to only use date functions and the provided formats.
As an added point if you have a date, store it as a date. It'll save a world of bother later on.

Date arithmetic in SQL on DB2/ODBC

I'm building a query against a DB2 database, connecting through the IBM Client Access ODBC driver. I want to pull fields that are less than 6 days old, based on the field 'a.ofbkddt'... the problem is that this field is not a date field, but rather a DECIMAL field, formatted as YYYYMMDD.
I was able to break down the decimal field by wrapping it in a call to char(), then using substr() to pull the year, month and day fields. I then formatted this as a date, and called the days() function, which gives a number that I can perform arithmetic on.
Here's an example of the query:
select
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM-
concat substr(char(a.ofbkddt),7,2) ) as difference, -- DD
a.ofbkddt as mydate
from QS36F.ASDF a
This yields the following:
difference mydate
2402 20050402
2025 20060306
...
4 20110917
3 20110918
2 20110919
1 20110920
This is what I expect to see... however when I use the same logic in the where clause of my query:
select
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM-
concat substr(char(a.ofbkddt),7,2) ) as difference, -- DD
a.ofbkddt as mydate
from QS36F.ASDF a
where
(
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM
concat substr(char(a.ofbkddt),7,2) ) -- DD
) < 6
I don't get any results back from my query, even though it's clear that I am getting date differences of as little as 1 day (obviously less than the 6 days that I'm requesting in the where clause).
My first thought was that the return type of days() might not be an integer, causing the comparison to fail... according to the documentation for days() found at http://publib.boulder.ibm.com/iseries/v5r2/ic2924/index.htm?info/db2/rbafzmst02.htm, it returns a bigint. I cast the difference to integer, just to be safe, but this had no effect.
You're going about this backwards. Rather than using a function on every single value in the table (so you can compare it to the date), you should pre-compute the difference in the date. It's costing you resources to run the function on every row - you'd save a lot if you could just do it against CURRENT_DATE (it'd maybe save you even more if you could do it in your application code, but I realize this might not be possible). Your dates are in a sortable format, after all.
The query looks like so:
SELECT ofbkddt as myDate
FROM QS36F.ASDF
WHERE myDate > ((int(substr(char(current_date - 6 days, ISO), 1, 4)) * 10000) +
(int(substr(char(current_date - 6 days, ISO), 6, 2)) * 100) +
(int(substr(char(current_date - 6 days, ISO), 9, 2))))
Which, when run against your sample datatable, yields the following:
myDate
=============
20110917
20110918
20110919
20110920
You might also want to look into creating a calendar table, and add these dates as one of the columns.
What if you try a common table expression?
WITH A AS
(
select
days( current date) -
days( substr(char(a.ofbkddt),1,4) concat '-' -- YYYY-
concat substr(char(a.ofbkddt),5,2) concat '-' -- MM-
concat substr(char(a.ofbkddt),7,2) ) as difference, -- DD
a.ofbkddt as mydate
from QS36F.ASDF a
)
SELECT
*
FROM
a
WHERE
difference < 6
Does your data have some nulls in a.ofbkddt? Maybe this is causing some funny behaviour in how db2 is evaluating the less than operation.