Formatting error while creating report using Shell Script - sql

HI all I am fairly new to Shell Scripting .. I was testing a sample report in which I was trying to spool the output of sql query embedded in shell script. here is my code
#!/bin/sh
ORACLE_ACCESS=hr/hr#xe
# Report file location
FILE_LOCATION=/home/$USER/Documents/loaddata/
#File Name
FILE_NAME=Report_`date +%y%m%d`.csv
sqlplus -s $ORACLE_ACCESS <<EOF 2>log.txt
set serveroutout on
set echo off
set first_name format A120
spool ${FILE_LOCATION}${FILE_NAME}
select first_name,last_name
from employees;
exit;
EOF
sql_error=$?
if [$sql_error !=0]; then
echo "Error"
exit 1
fi
However I am getting a pretty badly formatted output.
below is the sample
FIRST_NAME LAST_NAME
Ellen Abel
Sundar Ande
Mozhe Atkinson
David Austin
Hermann Baer
Shelli Baida
Amit Banda
Elizabeth Bates
Sarah Bell
David Bernstein
Laura Bissot
FIRST_NAME LAST_NAME
Harrison Bloom
Alexis Bull
Anthony Cabrio
Gerald Cambrault
Nanette Cambrault
John Chen
Kelly Chung
Karen Colmenares
My intended output should look something like below
First_name Last_name
Atlas Levine
John Doe
can somebody help?

Is your intended output like
First_name Last_name
Atlas Levine
John Doe
If so you can use something like set pagesize 10000 or something large so that the header doesnt get repeated. If you want to skip the header you can just set it to 0 You can refer the answers and links in Formatting output of queries in SQLPlus along with many other similar questions

Related

Get name(s) from JSON format column, that not in 2 other columns with names

I need to create column with name(s) (Supervisors - can be multiple supervisors at the same time, but also there might not be supervisor at all) from JSON format column, that not in 2 other column with names (Employee and Client).
Id
Employee
Client
AllParticipants
1
Justin Bieber
Ariana Grande
[{"ParticipantName":"Justin Bieber"},{"ParticipantName":"Ariana Grande"}]
2
Lionel Messi
Christiano Ronaldo
[{"ParticipantName":"Christiano Ronaldo"},{"ParticipantName":"Lionel Messi"}]
3
Nicolas Cage
Robert De Niro
[{"ParticipantName":"Robert De Niro"},{"ParticipantName":"Nicolas Cage"},{"ParticipantName":"Brad Pitt"}]
4
Harry Potter
Ron Weasley
[{"ParticipantName":"Ron Weasley"},{"ParticipantName":"Albus Dumbldor"},{"ParticipantName":"Harry Potter"},{"ParticipantName":"Lord Voldemort"}]
5
Tom Holland
Henry Cavill
[{"ParticipantName":"Henry Cavill"},{"ParticipantName":"Tom Holland"}]
6
Spider Man
Venom
[{"ParticipantName":"Venom"},{"ParticipantName":"Iron Man"},{"ParticipantName":"Superman"},{"ParticipantName":"Spider Man"}]
7
Andrew Garfield
Leonardo DiCaprio
[{"ParticipantName":"Tom Cruise"},{"ParticipantName":"Andrew Garfield"},{"ParticipantName":"Leonardo DiCaprio"}]
8
Dwayne Johnson
Jennifer Lawrence
[{"ParticipantName":"Jennifer Lawrence"},{"ParticipantName":"Dwayne Johnson"}]
The output column I need:
Supervisors
NULL
NULL
Brad Pitt
Albus Dumbldor, Lord Voldemort
NULL
Iron Man, Superman
Tom Cruise
NULL
I've tried to create extra columns to use Case expression after that, but it seems too complex.
SELECT *,
JSON_VALUE(w.AllParticipants,'$[0].ParticipantName') AS ParticipantName1,
JSON_VALUE(w.AllParticipants,'$[1].ParticipantName') AS ParticipantName2,
JSON_VALUE(w.AllParticipants,'$[2].ParticipantName') AS ParticipantName3,
JSON_VALUE(w.AllParticipants,'$[3].ParticipantName') AS ParticipantName4
FROM Work AS w
I'm wondering if there is an easy way to compare values and extract only unique ones.

How to continue a sequence when inserting

I have tried to simplify my question with the following example:
I have a table with the following data:
Marker Name Location
1 Eric Benson Mixed
2 John Smith Rural
3 A David Rural
4 B John Mixed
And i want to insert into the table:
Name Location
Andy Jones Mixed
Ian Davies Rural
How can i continue the sequencein the Marker column to end up with:
Marker Name Location
1 Eric Benson Mixed
2 John Smith Rural
3 A David Rural
4 B John Mixed
5 Andy Jones Mixed
6 Ian Davies Rural
If you make this with a Stored Procedure you can ask the max of the Marker before to insert.
(That only works if the Marker Column is not identity)
Like This:
declare #max_marker int
set #max_marker=isnull((select max(marker) from table),0)
--Insert comes here
Insert into table (Marker,Name,Location) Values(#max_marker+1,'Andy Jones','Mixed')

SQL Update conservating actual data

I have a Column named 'Complete name'
I need to update people with any last name 'Smiht' to 'Smith' without losing the name and the second last name.
For example, now I have:
John Smiht G.
Sarah Connor Smiht
John Ford Connor
James Smiht Ford
And the result of update has to be the same data but with Smiht being replaced to Smith:
John Smith G.
Sarah Connor Smith
John Ford Connor
James Smith Ford
Thanks!
The generic method is something like this:
update t
set CompleteName = replace(CompleteName, ' Smiht', ' Smith'
where CompleteName like '% Smiht%';

duplicate fields with an inner join

I'm having trouble understanding how to do a multi-table join without generating lots of duplicate fields.
Let's say that I have three tables:
family: id, name
parent: id, family, name
child: id, family, name
If I do a simple select:
select family.id, family.name from family
order by family.id;
I get a simple list:
ID Name
1 Smith
2 Jones
3 Wong
If I add an inner join:
select family.id, family.name, parent.first_name, parent.last_name
from family
inner join parent
on parent.family = family.id
order by family.id;
I get some duplicated fields:
ID Name Parent
1 Smith Howard Smith
1 Smith Janet Smith
2 Jones Phil Jones
2 Jones Harriet Jones
3 Wong Billy Wong
3 Wong Rachel Wong
And if I add another inner join:
select family.id, family.name, parent.first_name, parent.last_name
from family
inner join parent
on parent.family = family.id
inner join child
on child.family = family.id
order by family.id;
I get even more duplicated fields:
ID Name Parent Child
1 Smith Howard Smith Peter Smith
1 Smith Howard Smith Sally Smith
1 Smith Howard Smith Fred Smith
1 Smith Janet Smith Peter Smith
1 Smith Janet Smith Sally Smith
1 Smith Janet Smith Fred Smith
2 Jones Phil Jones Mark Jones
2 Jones Phil Jones Melissa Jones
2 Jones Harriet Jones Mark Jones
2 Jones Harriet Jones Melissa Jones
3 Wong Billy Wong Mary Wong
3 Wong Billy Wong Jennifer Wong
3 Wong Rachel Wong Mary Wong
3 Wong Rachel Wong Jennifer Wong
What I would prefer, because it's more human readable, is something like this:
ID Name Parent Child
1 Smith Howard Smith Peter Smith
Janet Smith Sally Smith
Fred Smith
2 Jones Phil Jones Mark Jones
Harriet Jones Melissa Jones
3 Wong Billy Wong Mary Wong
Rachel Wong Jennifer Wong
I know that one of the benefits of an inner join is to avoid presenting excess information through a Cartesian product. But it seems that I get something similar with a multi-table join. Is there a way to summarize each group as shown above or will this require post-processing with a scripting language like Python?
Thanks,
--Dan
This is precisely the way the relation databases work: each row must contain all information in itself, with every single field that you request. In other words, each row needs to make sense in isolation from all other rows. If you do a single query and you need to get all three levels of information, you need to deal with eliminating duplicates yourself for the desired formatting.
Alternatively, you can run three separate queries, and then do in-memory joins in code. Although this may be desirable in certain rare situations, it is generally a wrong way of spending your development time, because RDBMS are usually much more efficient at joining relational data.
You've hit it on the head. You'll need some post processing to get the results you're looking for.
SQL query results are always simple tabular data, so to get the results you're looking for would definitely not be a pretty query. You could do it, but it would involve quite a bit of query voodoo, storing things in temporary tables or using cursors, or some other funky workaround.
I'd definitely suggest using an external application to retrieve your data and format it appropriately from there.
ORMs like Entity Framework in .NET can probably do this pretty easily, but you could definitely do this with a few nested collections or dictionaries in any language.

Finding user names with particular characters in their last name

In Oracle SQL, I wish to find all user names,whose Last name contains some specific Characters like ('Z','X','D','F') Or contains Some Range of Characters from 'A-F'.
I tried this:
SELECT user_last_name
FROM userbase
WHERE user_last_name LIKE '%A%' OR user_last_name LIKE '%F%' .
So How can I go about it.
And I written facebook in question although its not directly related to it,because,its the example given by my sir.
UPDATE: I tried the above code,it works with so many OR's, but How can we define some range to search for like IN('Z','X','D','F') or IN ('A-F')
If you are using a recent version of Oracle, you should be able to use regular expressions
SQL> ed
Wrote file afiedt.buf
1 select first_name, last_name
2 from employees
3* where regexp_like( last_name, 'Z|X|D|[A-F]' )
SQL> /
FIRST_NAME LAST_NAME
-------------------- -------------------------
Ellen Abel
Sundar Ande
Mozhe Atkinson
David Austin
Hermann Baer
Shelli Baida
Amit Banda
Elizabeth Bates
Sarah Bell
David Bernstein
Laura Bissot
Harrison Bloom
Alexis Bull
Anthony Cabrio
Gerald Cambrault
Nanette Cambrault
John Chen
Kelly Chung
Karen Colmenares
Curtis Davies
Lex De Haan
Julia Dellinger
Jennifer Dilly
Louise Doran
Bruce Ernst
Alberto Errazuriz
Britney Everett
Daniel Faviet
Pat Fay
Kevin Feeney
Jean Fleaur
Tayler Fox
Adam Fripp
Samuel McCain
Allan McEwen
Donald OConnell
Eleni Zlotkey
37 rows selected.
If you want the search to be case-insensitive
SQL> ed
Wrote file afiedt.buf
1 select first_name, last_name
2 from employees
3* where regexp_like( last_name, 'Z|X|D|[A-F]', 'i' )
SQL> /
FIRST_NAME LAST_NAME
-------------------- -------------------------
Ellen Abel
Sundar Ande
Mozhe Atkinson
David Austin
Hermann Baer
Shelli Baida
Amit Banda
Elizabeth Bates
Sarah Bell
David Bernstein
Laura Bissot
Harrison Bloom
Alexis Bull
Anthony Cabrio
Gerald Cambrault
Nanette Cambrault
John Chen
Kelly Chung
Karen Colmenares
Curtis Davies
Lex De Haan
<<snip>>
Matthew Weiss
Jennifer Whalen
Eleni Zlotkey
93 rows selected.
You can use INSTR to test whether characters exist in your field, like so:
SELECT
user_last_name
FROM
userbase
WHERE 0 < INSTR(user_last_name,'A')
or 0 < INSTR(user_last_name,'B')
...repeat for each character you want to test for...