I have Year & Month but need to incorpate month number also - oracle11g

This is my value in the table : FY20 JAN
And i am looking for 'FY20 (M01) JAN'. How can convert like this in Oracle 11g SQL query ?

First you convert your string to a value of DATE type. Anything enclosed in double quotes is somewhat hard coded and TO_DATE function ignores them as long as they match the characters in the input in their specific locations. Here FY are in location (index) 1 and 2.
alter session set nls_date_format = 'yyyy-mm-dd';
select to_date('FY20 JAN', '"FY"yy MON') d from dual;
D
----------
2020-01-01
Then, you apply another function TO_CHAR to the date value we got above to get the desired output.
select to_char(
to_date('FY20 JAN', '"FY"YY MON')
, '"FY"yy "(M"mm")" MON'
) c from dual;
C
-----------------------
FY20 (M01) JAN

Related

Is there any Oracle built-in function to convert date format and how to exclude weekends from the logic

The below code gives me the output of current review date and the next review date. Here the current review date is fixed to today's date.
I want to keep that as a user defined variable. I tried using the --> ReviewDate = &enter_date; but whichever format i put in the dialog box it gives me an error (i tried 08-06-2020, 06-08-2020, 08-Jun-2020, etc). Is there any built-in function in oracle which will convert the value I input to the correct system date which oracle will understand ?
Also, what should be the code if i want to exclude any weekends from my current logic ? Here the next review date is set to 6 months from current review date but i want my code to exclude the weekends from this.
Thanks!!
SET SERVEROUTPUT ON;
DECLARE
ReviewDate workforce.Jdate%TYPE;
BEGIN
ReviewDate := '08-06-2020';
ReviewDate_New := add_months(ReviewDate, 6);
dbms_output.put_line('Last Review Date: ' || '08-06-2020');
dbms_output.put_line('Next Review Date: ' || ReviewDate_New);
END;
The ANSI format for a date literal is DATE 'YYYY-NN-DD' so:
ReviewDate := DATE '2020-06-08';
To avoid weekends you would have to check the day of the week returned by the add_months function and then increment the date accordingly. to_char with the 'D' format returns you a number 1-7 for the day of the week, so something like:
CASE TO_CHAR(ReviewDate_New, 'D')
WHEN 6 THEN
ReviewDate_New := ReviewDate_New + 2;
WHEN 7 THEN
ReviewDate_New := ReviewDate_New + 1;
ELSE
NULL; -- Do nothing
END CASE;
This assumes that Saturdays and Sundays are day 6 and 7 in your database (it depends on NLS settings).

When casting a datetime as date, why does SQLite3 only return the year and not the full date?

I know that you can cast a datetime to date using the date() function:
sqlite> select date('2000-01-01 10:00:00');
2000-01-01
But why does SQLite3's cast expression such as in
sqlite> select cast('2000-01-01 10:00:00' as date);
2000
only return the year?
Even using an explicit datetime() setup solely returns the year:
sqlite> select cast(datetime('2000-01-01 10:00:00') as date);
2000
Or:
sqlite> select cast(datetime('now') as date);
2019
Looking at Postgresql, it resolves both properly:
postgresql> select date('2000-01-01 10:00:00');
2000-01-01
postgresql> select cast('2000-01-01 10:00:00' as date);
2000-01-01
What's the technical explanation for SQLite3's – to me unexpected – behavior?
For SQLite there is no Date datatype. As mentioned in their documentation here: https://www.sqlite.org/datatype3.html
What you use as Date is actually TEXT.
You can check that:
select typeof(datetime('now'));
returns:
text
And:
select typeof(cast(datetime('now') as date));
returns:
integer
So the result of cast('2000-01-01 10:00:00' as date) is an integer and it's the same
integer that you get by:
select '2000-01-01 10:00:00' + 0
when SQLite implicitly converts '2000-01-01 10:00:00' to 2000 in order to use it in a mathematical operation.
In the case of dates it happens to be the numeric value of the year, but in general SQLite returns the longest substring of the TEXT, starting from the 1st character, that can be represented as an integer.
So for '2000-01-01 10:00:00' it's the substring until the 1st -, which is the year.

Transpose rows to columns in SQLite

I have data like this:
I am trying to transform it to this (using SQLite). In the desired result, within each id, each start should be on the same row as the chronologically closest end. If an id has a start but no end (like id=4), then the corresponding end, will be empty (as shown below).
I have tried this
select
id,
max( case when start_end = "start" then date end) as start,
max(case when start_end = "end" then date end ) as end
from df
group by id
But the result is this, which is wrong because id=5 only have one row, when it should have two:
id start end
1 2 1994-05-01 1996-11-04
2 4 1979-07-18 <NA>
3 5 2010-10-01 2012-10-06
Any help is much appreciated
CREATE TABLE mytable(
id INTEGER NOT NULL PRIMARY KEY
,start_end VARCHAR(5) NOT NULL
,date DATE NOT NULL
);
INSERT INTO mytable(id,start_end,date) VALUES (2,'start','1994-05-01');
INSERT INTO mytable(id,start_end,date) VALUES (2,'end','1996-11-04');
INSERT INTO mytable(id,start_end,date) VALUES (4,'start','1979-07-18');
INSERT INTO mytable(id,start_end,date) VALUES (5,'start','2005-02-01');
INSERT INTO mytable(id,start_end,date) VALUES (5,'end','2009-09-17');
INSERT INTO mytable(id,start_end,date) VALUES (5,'start','2010-10-01');
INSERT INTO mytable(id,start_end,date) VALUES (5,'end','2012-10-06');
select
s.id as id,
s.date as 'start',
min(e.date) as 'end' -- earliest end date from "same id&start"
from
-- only start dates
(select id, date
from intable
where start_end='start'
) as s
left join -- keep the start-only lines
-- only end dates
(select id, date
from intable
where start_end='end'
) as e
on s.id = e.id
and s.date < e.date -- not too early
group by s.id, s.date -- "same id&start"
order by s.id, s.date; -- ensure sequence
Left join (to keep the start-only line for id "4") two on-the-fly tables, start dates and end dates.
Take the minimal end date which is just higher than start date (same id, using min()and group by.
Order by id, then start date.
I tested this on a test table which is similar to your dump, but has no "NOT NULL" and no "PRIMARY KEY". I guess for this test table that is irrelevant; otherwise explain the effect, please.
Note:
Internally three pairs of dates for id 5 (those that match end>start) are found, but only those are forwarded with the lowest end (min(end)) for each of the two different combinations of ID and start group by ID, start. The line where end>start but end not being the minimum is therefor not returned. That makes two lines with start/end pairs as desired.
Output (with .headers on):
id|start|end
2|1994-05-01|1996-11-04
4|1979-07-18|
5|2005-02-01|2009-09-17
5|2010-10-01|2012-10-06
UPDATE: Incorporate helpful comments by #MatBailie.
Thank you! This is exactly what I needed to do, only with a few changes:
SELECT
s.value AS 'url',
"AVGDATE" AS 'fieldname',
sum(e.value)/count(*) AS 'value'
FROM
(SELECT url, value
FROM quicktag
WHERE fieldname='NAME'
) AS s
LEFT JOIN
(SELECT url, substr(value,1,4) AS value
FROM quicktag
WHERE fieldname='DATE'
) AS e
ON s.url = e.url
WHERE e.value != ""
GROUP BY s.value;
I had a table like this:
url fieldname value
---------- ---------- ----------
1000052801 NAME Thomas
1000052801 DATE 2007
1000131579 NAME Morten
1000131579 DATE 2005
1000131929 NAME Tanja
1000131929 DATE 2014
1000158449 NAME Knud
1000158449 DATE 2007
1000158450 NAME Thomas
1000158450 DATE 2003
I needed to correlate NAME and DATE in columns based on url as a key, and generate a field with average DATE grouped by multiple NAME fields.
So my result looks like this:
url fieldname value
---------- ---------- ----------
Thomas AVGDATE 2005
Morten AVGDATE 2005
Tanja AVGDATE 2014
Knud AVGDATE 2007
Unfortunately I not have enough posts to make my vote count yet.

How to convert the Long value to String using sql

I am doing a long to string conversion using java in following way.
Long longValue = 367L;
String str = Long.toString(longValue, 36).toUpperCase();
this is returning me as value A7. how can achieve this in doing oracle sql.
UPDATED:
Hi, I have analyzed how java code is working then wanted to implement the same thing in procedure.
First point is Input vaues. LONG and Radix. in my case Radix is 36. so i will have values from 1..9A...Z0 It picks up the values from this set only.
Second point Long value as input. we have to divide this value with radix. if the quotient is more than 36 again we need to divide.
For eaxmple 367 then my converted value is 10(quotient) 7(remainder) that is A7.
3672 converted value is 102 0 i need to do again for 102 that is 2 -6 so my final value will be 2-6 0 that is 2U0(- means reverse the order).
UPDATE 2:
Using oracle built in functions we can do this. this was solved by my friend and gave me a function.I want to thank my friend. this will give me an out put as follows.
367 then my converted value is 10(quotient) 7(remainder) that is *A*7.(I modified this to my requirement).
FUNCTION ENCODE_STRING(BASE_STRING IN VARCHAR2,
FROM_BASE IN NUMBER,
TO_BASE IN NUMBER)
RETURN VARCHAR2
IS
V_ENCODED_STRING VARCHAR(100);
BEGIN
WITH N1 AS (
SELECT SUM((CASE
WHEN C BETWEEN '0' AND '9'
THEN TO_NUMBER(C)
ELSE
ASCII(C) - ASCII('A') + 10
END) * POWER(FROM_BASE, LEN - RN)
) AS THE_NUM
FROM (SELECT SUBSTR(BASE_STRING, ROWNUM, 1) C, LENGTH(BASE_STRING) LEN, ROWNUM RN
FROM DUAL
CONNECT BY ROWNUM <= LENGTH(BASE_STRING))
),
N2 AS (
SELECT (CASE
WHEN N < 10
THEN TO_CHAR(N)
ELSE CHR(ASCII('A') + N - 10)
END) AS DIGI, RN
FROM (SELECT MOD(TRUNC(THE_NUM/POWER(TO_BASE, ROWNUM - 1)), TO_BASE) N, ROWNUM RN
FROM N1
CONNECT BY ROWNUM <= TRUNC(LOG(TO_BASE, THE_NUM)) + 1)
)
SELECT SYS_CONNECT_BY_PATH(DIGI, '*') INTO V_ENCODED_STRING
FROM N2
WHERE RN = 1
START WITH RN = (SELECT MAX(RN) FROM N2)
CONNECT BY RN = PRIOR RN - 1;
RETURN V_ENCODED_STRING;
IN PL/SQL (or Oracle SQL) you have the a function called TO_CHAR.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions181.htm
It is not possible to do it in the pure SQL. You have to use PL/SQL.
Simple example how to do it PL/SQL:
CREATE TABLE long_tbl
(
long_col LONG
);
INSERT INTO long_tbl VALUES('How to convert the Long value to String using sql');
DECLARE
l_varchar VARCHAR2(32767);
BEGIN
SELECT long_col
INTO l_varchar
FROM long_tbl;
DBMS_OUTPUT.PUT_LINE(l_varchar);
END;
-- How to convert the Long value to String using sql
There is TO_LOB function but it can only by used when you insert data into table.
http://docs.oracle.com/cd/B19306_01/server.102/b14200/functions185.htm
You can apply this function only to a LONG or LONG RAW column, and
only in the select list of a subquery in an INSERT statement.
There is also other, more proper way to do it by using "dbms_sql.column_value_long" but this gets complicated (fetching of the LONG column and appending to the CLOB type.)
http://docs.oracle.com/cd/B19306_01/appdev.102/b14258/d_sql.htm#i1025399
(Oracle Database PL/SQL Packages and Types Reference)

Getting All the record of particular month - Building SQL Query

I need some help to build SQL Query. I have table having data like:
ID Date Name
1 1/1/2009 a
2 1/2/2009 b
3 1/3/2009 c
I need to get result something like...
1 1/1/2009 a
2 1/2/2009 b
3 1/3/2009 c
4 1/4/2009 Null
5 1/5/2009 Null
6 1/6/2009 Null
7 1/7/2009 Null
8 1/8/2009 Null
............................
............................
............................
30 1/30/2009 Null
31 1/31/2009 Null
I want query something like..
Select * from tbl **where month(Date)=1 AND year(Date)=2010**
Above is not completed query.
I need to get all the record of particular month, even if some date missing..
I guess there must be equi Join in the query, I am trying to build this query using Equi join
Thanks
BIG EDIT
Now understand the OPs question.
Use a common table expression and a left join to get this effect.
DECLARE #FirstDay DATETIME;
-- Set start time
SELECT #FirstDay = '2009-01-01';
WITH Days AS
(
SELECT #FirstDay as CalendarDay
UNION ALL
SELECT DATEADD(d, 1, CalendarDay) as CalendarDay
FROM Days
WHERE DATEADD(d, 1, CalendarDay) < DATEADD(m, 1, #FirstDay)
)
SELECT DATEPART(d,d.CalendarDay), **t.date should be (d.CalendarDay)**, t.Name FROM Days d
LEFT JOIN tbl t
ON
d.CalendarDay = t.Date
ORDER BY
d.CalendarDay;
Left this original answer at bottom
You need DATEPART, sir.
SELECT * FROM tbl WHERE DATEPART(m,Date) = 1
If you want to choose month and year, then you can use DATEPART twice or go for a range.
SELECT * FROM tbl WHERE DATEPART(m,Date) = 1 AND DATEPART(yyyy,Date) = 2009
Range :-
SELECT * FROM tbl WHERE Date >= '2009-01-01' AND Date < '2009-02-01'
See this link for more info on DATEPART.
http://msdn.microsoft.com/en-us/library/ms174420.aspx
You can use less or equal to.
Like so:
select * from tbl where date > '2009-01-01' and date < '2009-02-01'
However, it is unclear if you want month 1 from all years?
You can check more examples and functions on "Date and Time Functions" from MSDN
Create a temporary table containing all days of that certain month,
Do left outer join between that table and your data table on tempTable.month = #month.
now you have a big table with all days of the desired month and all the records matching the proper dates + empty records for those dates who have no data.
i hope that's what you want.

Resources