SQL query that returns a date - sql

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;

Related

how to convert date format in sqlite (from dd/mm/yy to dd/mm/yyyy) and (d/m/yy to dd/mm/yyyy) in sqlite database

I want to format date in a column where date formats are mixed like d/mm/yy, d/m/yy, dd/mm/yyyy where i want ot format all values should be in one format like mm/dd/yyyy in sqlite database
SQLite does not support built-in date and/or time storage class. Instead, it leverages some built-in date and time functions to use other storage classes such as TEXT, REAL, or INTEGER for storing the date and time values.
use the TEXT storage class for storing SQLite date and time https://www.sqlitetutorial.net/sqlite-date/
This will convert month, day, year divided by slashes into year, month, day divided by dashes. For example 2/19/1921 into 1921-2-19. Just uses basic SQL with a subquery.
SELECT
surveydate
,Substr(dayyear, Instr(dayyear, '/') + 1, 999) || '-' || -- Year
month || '-' || -- Month
Substr(dayyear, 0, Instr(dayyear, '/')) -- Day
AS surveydate2
FROM (
SELECT
surveydate,
Substr(surveydate, 0, Instr(surveydate, '/')) AS month,
Substr(surveydate, Instr(surveydate, '/') + 1, 999) AS dayyear
FROM "input_locations"
)

How do I convert dates in SqlLite from m/d/y to Y-m-d so that I can use strftime

I have a set of data that I am importing into SqlLite, but don't really have the opportunity to manipulate it before insertion. I am trying to calculate "age" of the date, but this is proving very difficult in its current format.
I am looking for a select that I can use to update the data and then begin writing queries the way I want.
Data Samples
9/20/1983
2/18/1986
8/1/1994
5/29/1999
Desired
1983-09-20
1986-02-18
1994-08-01
1999-05-29
Once I have data in that format, I will calculate the date using the following
(strftime('%Y', 'now') - strftime('%Y', Born)) - (strftime('%m-%d', 'now') < strftime('%m-%d', BOrn))
I guess if there's a way to cast the date into the right format and calculate the age in one query, that would save a step, but I haven't been able to find a way so far.
You could use the following update statement to change the date format to YYYY-MM-DD:
update t
set Born =
substr(Born, -4) || '-' ||
substr('0' || substr(Born, 1, instr(Born, '/')-1), -2) || '-' ||
substr('0' || substr(Born, instr(Born, '/')+1,
length(Born)-5-instr(Born, '/')), -2)
where substr(Born, -5, 1) = '/'
and Born LIKE '%/%/%'
The where clause is there to only update dates that have a d/m/yyyy format, where d and m could be two digits as well.

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;

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.

SQL Select between dates

I am running sqlite to select data between two ranges for a sales report. To select the data from between two dates I use the following statement:
SELECT * FROM test WHERE date BETWEEN "11/1/2011" AND "11/8/2011";
This statement grabs all the dates even those outside the criteria. The date format you see entered is in the same format that I get back. I'm not sure what's wrong.
SQLite requires dates to be in YYYY-MM-DD format. Since the data in your database and the string in your query isn't in that format, it is probably treating your "dates" as strings.
Change your data to that formats to use sqlite datetime formats.
YYYY-MM-DD
YYYY-MM-DD HH:MM
YYYY-MM-DD HH:MM:SS
YYYY-MM-DD HH:MM:SS.SSS
YYYY-MM-DDTHH:MM
YYYY-MM-DDTHH:MM:SS
YYYY-MM-DDTHH:MM:SS.SSS
HH:MM
HH:MM:SS
HH:MM:SS.SSS
now
DDDDDDDDDD
SELECT * FROM test WHERE date BETWEEN '2011-01-11' AND '2011-08-11'
One more way to select between dates in SQLite is to use the powerful strftime function:
SELECT * FROM test WHERE strftime('%Y-%m-%d', date) BETWEEN "11-01-2011" AND "11-08-2011"
These are equivalent according to https://sqlite.org/lang_datefunc.html:
date(...)
strftime('%Y-%m-%d', ...)
but if you want more choice, you have it.
SELECT *
FROM TableName
WHERE julianday(substr(date,7)||'-'||substr(date,4,2)||'-'||substr(date,1,2)) BETWEEN julianday('2011-01-11') AND julianday('2011-08-11')
Note that I use the format: dd/mm/yyyy.
If you use d/m/yyyy, Change in substr().
Or you can cast your string to Date format with date function. Even the date is stored as TEXT in the DB.
Like this (the most workable variant):
SELECT * FROM test WHERE date(date)
BETWEEN date('2011-01-11') AND date('2011-08-11')
SQLite does not have a concept of dates. It only knows them as text. When you do this in SQLite you're actually doing string comparisons. You can read more from the official documentation.
When two TEXT values are compared an appropriate collating sequence is used to determine the result.
Any numeric (i.e., not using words like 'May') format for dates that is padded and in order from biggest field to smallest field will work. "2021-05-07" (May 7th) comes before "2021-05-09" (May 9th). So if you use "yyyy-mm-dd" format then you'll be set. "yyyy/mm/dd" and "yyyymmdd" work just fine too. (For a better phrasing on "sortable" date formats check out RFC 3339 section 5.1.)
A reason to use "yyyy-mm-dd" format is because that's the format that SQLite's builtin date uses.
Special thanks to Jeff and vapcguy your interactivity is really encouraging.
Here is a more complex statement that is useful when the length between '/' is unknown::
SELECT * FROM tableName
WHERE julianday(
substr(substr(date, instr(date, '/')+1), instr(substr(date, instr(date, '/')+1), '/')+1)
||'-'||
case when length(
substr(date, instr(date, '/')+1, instr(substr(date, instr(date, '/')+1),'/')-1)
)=2
then
substr(date, instr(date, '/')+1, instr(substr(date, instr(date, '/')+1), '/')-1)
else
'0'||substr(date, instr(date, '/')+1, instr(substr(date, instr(date, '/')+1), '/')-1)
end
||'-'||
case when length(substr(date,1, instr(date, '/')-1 )) =2
then substr(date,1, instr(date, '/')-1 )
else
'0'||substr(date,1, instr(date, '/')-1 )
end
) BETWEEN julianday('2015-03-14') AND julianday('2015-03-16')
Put the variable in the Where Condition and parse both dates using 'BETWEEN':
SELECT * FROM emp_master
-> if you have date formate like dd/mm/yyyy simple then,
WHERE joined_date BETWEEN '01/03/2021' AND '01/09/2021';
-> and if you have date formate like yyyy/mm/dd then,
WHERE joined_date BETWEEN '2021/03/01' AND '2021/09/01';
☻♥ Done Keep Code.
Let's say you are preparing data for some report. Then the whole ordeal will look similar to this.
--add column with date in ISO 8601
ALTER TABLE sometable ADD COLUMN DateInISO8601;
--update the date from US date to ISO8601 date
UPDATE sometable
SET DateInISO8601 = substr([DateInUSformat],length([DateInUSformat])+1, -4)
|| '-' ||
substr('00' || [DateInUSformat],instr('00' || [DateInUSformat],'/'),-2)
|| '-' ||
substr('00' || rtrim(substr([DateInUSformat],instr([DateInUSformat],'/')+1,2),'/'),-2,2);
SELECT DateInISO8601
FROM sometable
WHERE DateInISO8601 BETWEEN '2022-02-02' AND '2022-02-22';
You can of course do all that on the fly, but if you have the choice -- don't. Use the ISO date by default and convert it on the way in and out to SQLite DB.