How to find last date of current year in db2 - sql

I want to find the last date for current year. As of now i am doing it like below and it is giving me right result '2016-12-31'. but i want to know is there any possible function to do this -
SELECT date(substr(current_date,1, 4)||'-'|| '12-31') FROM SYSIBM.SYSDUMMY1

Slightly shorter and faster because of datetime function YEAR:
values(year(current_date) || '-12-31')
The above is for testing on the DB2 command prompt, a fully SELECT would be:
select year(current_date) || '-12-31' from sysibm.sysdummy1

Related

storing date in 'CCYYMMDD' format in Teradata

I would like to store dates in the format CCYYMMDD in Teradata, but I fail to do so. Find below what I tried so far:
query 1:
SEL CAST(CAST(CURRENT_DATE AS DATE FORMAT 'YYYYMMDD') AS VARCHAR(8))
-- Output: 20191230 ==> this works!
query 2:
SEL CAST(CAST(CURRENT_DATE AS DATE FORMAT 'CCYYMMDD') AS VARCHAR(8))
-- output: SELECT Failed. [3530] Invalid FORMAT string 'CCYYMMDD'.
It seems that the CCYYMMDD is not available in Teradata right away. Is there a workaround?
Tool used: Teradata SQL assistant
Internally, dates are stored as integers in Teradata. So when you say you want to store them in a different format, I don't think you can do that. But you can choose how to display / return the values.
I'm sure there's a cleaner way to get the format you want, but here's one way:
WITH cte (mydate) AS (
SELECT CAST(CAST(CURRENT_DATE AS DATE FORMAT 'YYYYMMDD') AS CHAR(8)) AS mydate
)
SELECT
CAST(
(CAST(SUBSTRING(mydate FROM 1 FOR 2) AS INTEGER) + 1) -- generate "century" value
AS CHAR(2) -- cast value as string
) || SUBSTRING(mydate FROM 3) AS new_date -- add remaining portion of date string
FROM cte
SQL Fiddle - Postgres
You'd have to add some extra logic to handle years before 1000 and after 9999. I don't have a TD system to test, but give it a try and let me know.

SQL query that returns a date

My DB contains a period(month) and a year - I am trying to convert it to a date. I don't care for the actual day of the month so I have just made it "1" (the 1st of the month).
In my code I had to convert the "13th" period to the 12th because of the 12 months of the year, so my decode did that part... Ultimately, I want it to return as a date. I have a concatenation to make it 'look' like a date, but not actually a date.
What i do with the data is query it and return it in Excel for further manipulation. When imported to Excel, it does not import as a date nor does it let me convert to a date format.
SELECT DIA_PROJECT_DETAIL.FY_DC || '/' ||
decode(DIA_PROJECT_DETAIL.PER_DC,1,1,2, 2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,12)||
'/01' as "Date"
FROM AMS.DIA_PROJECT_DETAIL DIA_PROJECT_DETAIL
There has to be an easier or more effective way to do this!
There is no much simpler way. DECODE is fine for converting month 13 to month 12, but you use it a bit too complicated. Then you shouldn't rely on session settings, but explicitly tell the DBMS the date format your assembled string represents. Use TO_DATE with the appropriate format.
select
to_date(fy_dc || to_char(decode(per_dc, 13, 12, per_dc), '00') || '01', 'yyyymmdd')
as "Date"
from ams.dia_project_detail dia_project_detail;
Just use least():
SELECT (DIA_PROJECT_DETAIL.FY_DC || '/' ||
LEAST(DIA_PROJECT_DETAIL.PER_DC, 12) ||
'/01'
) as "Date"
FROM AMS.DIA_PROJECT_DETAIL DIA_PROJECT_DETAIL;

Selecting YYYYMM of the previous month in HIVE

I am using Hive, so the SQL syntax might be slightly different. How do I get the data from the previous month? For example, if today is 2015-04-30, I need the data from March in this format 201503? Thanks!
select
employee_id, hours,
previous_month_date--YYYYMM,
from
employees
where
previous_month_date = cast(FROM_UNIXTIME(UNIX_TIMESTAMP(),'yyyy-MM-dd') as int)
From experience, it's safer to use DATE_ADD(Today, -1-Day(Today)) to compute last-day-of-previous-month without having to worry about edge cases. From there you can do what you want e.g.
select
from_unixtime(unix_timestamp(), 'yyyy-MM-dd') as TODAY,
date_add(from_unixtime(unix_timestamp(), 'yyyy-MM-dd'), -1-cast(from_unixtime(unix_timestamp(), 'd') as int)) as LAST_DAY_PREV_MONTH,
substr(date_add(from_unixtime(unix_timestamp(), 'yyyy-MM-dd'), -1-cast(from_unixtime(unix_timestamp(), 'd') as int)), 1,7) as PREV_MONTH,
cast(substr(regexp_replace(date_add(from_unixtime(unix_timestamp(), 'yyyy-MM-dd'), -1-cast(from_unixtime(unix_timestamp(), 'd') as int)), '-',''), 1,6) as int) as PREV_MONTH_NUM
from WHATEVER limit 1
-- today last_day_prev_month prev_month prev_month_num
-- 2015-08-13 2015-07-30 2015-07 201507
See Hive documentation about date functions, string functions etc.
below works across year boundaries w/o complex calcs:
date_format(add_months(current_date, -1), 'yyyyMM') --previous month's yyyyMM
in general,
date_format(add_months(current_date, -n), 'yyyyMM') --previous n-th month's yyyyMM
use proper sign for needed direction (back/ahead)
You could do (year('2015-04-30')*100+month('2015-04-30'))-1 for the above mentioned date, it will return 201503 or something like (year(from_unixtime(unix_timestamp()))*100+month(from_unixtime(unix_timestamp())))-1 for today's previous month. Assuming your date column is in 'yyyy-mm-dd' format you can use the first example and substitute the date string with your table column name; for any other format the second example will do, add the column name in the unix_timestamp() operator.
Angelo's reply is a good start but it returns 201500 if the original date was 2015-01-XX. Building on his answer, I suggest using the following:
IF(month(${DATE}) = 1,
(year(${DATE})-1)*100 + 12,
year(${DATE})*100 + month(${DATE})-1
) as month_key
provided you get rid of those hyphens in your input string , previous date's month id in YYYYMM format you can get by:-
select if( ((${hiveconf:MonthId}-1)%100)=0 ,${hiveconf:MonthId}-89,${hiveconf:MonthId}-1 ) as PreviousMonthId;

Oracle error: ORA-01839: date not valid for month specified

OK guys, first of all, I have checked many websites about this error and, unfortunately, none of them helped me. I have the simple following query:
select * from (
select to_date(cal.year || cal.month || cal.day, 'yyyymmdd') as datew,
cal.daytype as type
from vw_calendar cal)
where datew > sysdate;
When I try to execute the entire query, this error shows up:
ORA-01839: date not valid for month specified
If I execute only the query:
select to_date(cal.year || cal.month || cal.day, 'yyyymmdd') as datew,
cal.daytype as type
from vw_calendar cal;
It worked absolutely fine. If you want to view the results of the query: http://pastebin.com/PV95g3ac
I checked the days of the month like day 31 or leap year and everything seems correct. I don't know what to do anymore. My database is a Oracle 10g and I tried to execute the query on SQL Developer and PL/SQL Developer. Same error on both IDE.
Actually the issue is some months have 30 days and some have 31, so the query which you are forming, it is trying to get 31st day of that month which is invalid and hence the error. For Example:
it may be trying for date like: 31-NOV-2016 which is not correct, NOV has only 30 days.
Well, I found a workaround, not a solution. If anyone knows the "correct" solution for this problem, I appreciate if you share with us. My "solution" convert the date to number and then compare with a sysdate (converted too). Take a look:
select * from
( select to_number(cal.year||cal.month||cal.day) as datew,
cal.daytype as type from vw_calendar cal ) a
where a.datew > to_number(to_char(sysdate, 'yyyymmdd'));
Thanks to everyone!
Use alias name for the inner query
select * from (
select to_date(cal.year || cal.month || cal.day, 'yyyymmdd') as datew,
cal.daytype as type
from vw_calendar cal) a
where a.datew > sysdate;

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.