I want to create a fixed length flat file (separated by ','), but when a field has a null value, the record moves. Please see illustration below (incorrect Jenny and Roland records):
Source Table:
Name Color Balance Zip Code
------- ------ ------- --------
Melissa Orange $200.00 40240
Karl Blue $150.00 40884
Jenny -null- -null- 45667
Roland -null- $110.00 53366
Vincent Green $285.00 45677
Output I want to get:
Correct_Ouput
----------------------------
Melissa,Orange,$200.00,40240
Karl ,Blue ,$150.00,40884
Jenny , , ,45667
Roland , ,$110.00,53366
Vincent,Green ,$285.00,45677
Output I want to get:
Wrong_Output
----------------------------
Melissa,Orange,$200.00,40240
Karl ,Blue ,$150.00,40884
Jenny ,,,45667
Roland ,,$110.00,53366
Vincent,Green ,$285.00,45677
I tried searching but I get the null to empty string result.
Please help. Thank you.
Use the COALESCE(column,' ') function.
For some databases, you can use IFNULL or NVL. See this web page for more details.
You could use NVL to replace the NULL value with required number of spaces to retain the format.
For example,
SQL> SELECT 'Karl' NAME,
2 NVL('Blue', ' ') color,
3 NVL('$150.00',' ') balance,
4 40884 zip_code
5 FROM dual
6 UNION ALL
7 SELECT 'Jenny' name,
8 NVL(NULL, ' ') color,
9 NVL(NULL,' ') balance,
10 45667 zip_code
11 FROM dual
12 /
NAME COLOR BALANCE ZIP_CODE
----- ----- --------- ----------
Karl Blue $150.00 40884
Jenny 45667
SQL>
You could also use DECODE.
For example,
DECODE(column, NULL, ' ')
Related
I have created a query to get the output like from table IRC_TABLE-
Requistion_number Name
12 John Mayer, Andrew,
11 Swastak,
I want if the values in Name has comma at the end and nothing beyond then it should be removed-
Requistion_number Name
12 John Mayer, Andrew
11 Swastak
Which function will help me achieve this ?
The easiest and probably most performant way to do this would be to use TRIM:
SELECT Requistion_number, TRIM(TRAILING ',' FROM Name) AS Name
FROM yourTable;
You could use also REGEXP_REPLACE here:
SELECT Requistion_number, REGEXP_REPLACE(Name, ',$', '') AS Name
FROM yourTable;
The regex option would be of more value if the replacement logic were more complex than just stripping off a certain final character.
Yet another option (apart from what Tim already said) is the rtrim (right-trim) function.
When we're searching for various options, even substr with case expression might do (but hey, you surely will not want to use it):
SQL> select * From your_table;
REQUISTION_NUMBER NAME
----------------- -------------------
122 John Mayer, Andrew,
111 Swastak,
333 No comma, here
SQL> select requistion_number,
2 rtrim(name, ',') as name_1,
3 substr(name, 1, length(name) - case when substr(name, -1) = ',' then 1
4 else 0
5 end) as name_2
6 from your_table;
REQUISTION_NUMBER NAME_1 NAME_2
----------------- ------------------- -------------------
122 John Mayer, Andrew John Mayer, Andrew
111 Swastak Swastak
333 No comma, here No comma, here
SQL>
Is there any way to compare two columns with strings to each other, and getting the matches?
I have two columns containing Names, once with the Full Name the other with (mostly) just the Surname.
I just tried it with soundex, but it will just return if the values are almost similar in both columns.
SELECT * FROM TABLE
WHERE soundex(FullName) = soundex(Surname)
1 John Doe Doe
2 Peter Parker Parker
3 Brian Griffin Brian Griffin
with soundex it will only match the 3rd line.
A simple option is to use instr, which shows whether surname exists in fullname:
SQL> with test (id, fullname, surname) as
2 (select 1, 'John Doe' , 'Doe' from dual union all
3 select 2, 'Peter Parker' , 'Parker' from dual union all
4 select 3, 'Brian Griffin', 'Brian Griffin' from dual
5 )
6 select *
7 from test
8 where instr(fullname, surname) > 0;
ID FULLNAME SURNAME
---------- ------------- -------------
1 John Doe Doe
2 Peter Parker Parker
3 Brian Griffin Brian Griffin
Another option is to use one of UTL_MATCH functions, e.g. Jaro-Winkler similarity which shows how well those strings match:
SQL> with test (id, fullname, surname) as
2 (select 1, 'John Doe' , 'Doe' from dual union all
3 select 2, 'Peter Parker' , 'Parker' from dual union all
4 select 3, 'Brian Griffin', 'Brian Griffin' from dual
5 )
6 select id, fullname, surname,
7 utl_match.jaro_winkler_similarity(fullname, surname) jws
8 from test
9 order by id;
ID FULLNAME SURNAME JWS
---------- ------------- ------------- ----------
1 John Doe Doe 48
2 Peter Parker Parker 62
3 Brian Griffin Brian Griffin 100
SQL>
Feel free to explore other function that package offers.
Also, note that I didn't pay attention to possible letter case differences (e.g. "DOE" vs. "Doe"). If you need that as well, compare e.g. upper(surname) to upper(fullname).
Please use instring function,
SELECT * FROM TABLE
WHERE instr(Surname, FullName) > 0;
SELECT * FROM TABLE
WHERE instr(upper(Surname), upper(FullName)) > 0;
SELECT * FROM TABLE
WHERE upper(FullName) > upper(Surname);
As far as I know there is nothing out of the box when matching becomes complicated. For the cases shown, however, the following expression would suffice:
where fullname like '%' || surname
Update
The main problem may be false positives:
The last name 'Park' appears in 'Peter Parker'. Above query solves this by looking at the full name's end.
Another problem may be upper / lower case as mentioned in the other answers (not shown in your sample data).
You want the last name 'PARKER' match 'Peter Parker'.
But when looking at the strings case insensitively, another problem arises:
The last name 'Strong' will suddenly match 'Louis Armstrong'.
A solution for this is to add a blank to make the difference:
where ' ' || upper(fullname) like '% ' || upper(surname)
' LOUIS ARMSTRONG' like '% STRONG' -> false
' LOUIS ARMSTRONG' like '% ARMSTRONG' -> true
' LOUIS ARMSTRONG' like '% LOUIS ARMSTRONG' -> true
Demo: https://dbfiddle.uk/?rdbms=oracle_18&fiddle=0ac5c80061b4aeac1153a8c5976e6e54
Let's say I've got the following database table
Name | Nickname | ID
----------------------
Joe Joey 14
Joe null 14
Now I want to do a select statement that merges these two columns to one while replacing the null values. The result should look like this:
Joe, Joey, 14
Which sql statement manages this (if it's even possible)?
Simplest solution:
SQL> select * from t69
2 /
NAME NICKNAME ID
---------- ---------- ----------
Joe Joey 14
Joe 14
Michael 15
Mick 15
Mickey 15
SQL> select max(name) as name
2 , max(nickname) as nickname
3 , id
4 from t69
5 group by id
6 /
NAME NICKNAME ID
---------- ---------- ----------
Joe Joey 14
Michael Mickey 15
SQL>
If you have 11gR2 you could use the new-fangled LISTAGG() function but otherwise it is simple enough to wrap the above statement in a SELECT which concatenates the NAME and NICKNAME columns.
AFAIK,
the question is not clear.so i am making some assumptions over here.
your output has the first and 3rd columns for both the rows as same.
Only the 2nd field is different.
so u can simply write a select quest
select one.name,two.nick_name,one.id from
(select name,id from your_tb group by name,id) one,
your_tb two
where two.nickname is not NULL
and two.name=one.name
and two.id=one.id;
may be we can tune this but i am not good in tuning sql squeries,but this is the way i suppose u need.
I'm trying to select data across multiple rows into one row.
For example, with this data set:
NAME THING DATE
----- ------ ------
JACK 1 EARLY
JACK 2 LATER
JACK 3 NOW
JANE 1 LATER
JANE 2 EARLY
JANE 3 NOW
I want to produce the following result:
NAME THING DATE
---- ---- -----
JACK 1, 2, 3 NOW
JANE 1, 2, 3 NOW
And so, I know i can use the LISTAGG function to combine the "Thing" rows, but my biggest question is how to select across multiple rows to get the "NOW" values in the date field.
Any help would be appreciated. Thanks!
It isn't clear if you want the latest date for any thing (ordering the aggregated things either by date or by their own values):
select name,
listagg(thing, ',') within group (order by date_col) as things,
max(date_col) as now
from your_table
group by name
order by name;
or the date corresponding to the highest value of thing:
select name,
listagg(thing, ',') within group (order by thing) as things,
max(date_col) keep (dense_rank last order by thing) as now
from your_table
group by name
order by name;
As you said those are actually dates, with your sample data with added date values configured slightly differently for two names:
NAME THING DATE_COL
---- ---------- ----------
JACK 1 2019-01-01
JACK 2 2019-03-15
JACK 3 2019-04-30
JANE 1 2019-02-01
JANE 2 2019-05-03
JANE 3 2019-04-02
the first query gets:
NAME THINGS NOW
---- --------------- ----------
JACK 1,2,3 2019-04-30
JANE 1,3,2 2019-05-03
and the second query gets:
NAME THINGS NOW
---- --------------- ----------
JACK 1,2,3 2019-04-30
JANE 1,2,3 2019-04-02
db<>fiddle
Let's say I've got the following database table
Name | Nickname | ID
----------------------
Joe Joey 14
Joe null 14
Now I want to do a select statement that merges these two columns to one while replacing the null values. The result should look like this:
Joe, Joey, 14
Which sql statement manages this (if it's even possible)?
Simplest solution:
SQL> select * from t69
2 /
NAME NICKNAME ID
---------- ---------- ----------
Joe Joey 14
Joe 14
Michael 15
Mick 15
Mickey 15
SQL> select max(name) as name
2 , max(nickname) as nickname
3 , id
4 from t69
5 group by id
6 /
NAME NICKNAME ID
---------- ---------- ----------
Joe Joey 14
Michael Mickey 15
SQL>
If you have 11gR2 you could use the new-fangled LISTAGG() function but otherwise it is simple enough to wrap the above statement in a SELECT which concatenates the NAME and NICKNAME columns.
AFAIK,
the question is not clear.so i am making some assumptions over here.
your output has the first and 3rd columns for both the rows as same.
Only the 2nd field is different.
so u can simply write a select quest
select one.name,two.nick_name,one.id from
(select name,id from your_tb group by name,id) one,
your_tb two
where two.nickname is not NULL
and two.name=one.name
and two.id=one.id;
may be we can tune this but i am not good in tuning sql squeries,but this is the way i suppose u need.