Selecting form with SUBSTR - sql

I have a table with name and profession I need to select the name of all employees with the first letter of their profession surrounded by () to be like:
Sara (D)
Jack (E)

Use || to concatenate strings and SUBSTR() to get the first character:
SELECT name || ' (' || SUBSTR( profession, 1,, 1 ) || ')'
FROM your_table;

Related

how to check for duplicate rows of all the columns

I want to check for duplicate rows . and see there column values .
if there were only few columns in my table - 2 for example - I would have done something like:
'''
select col1, col2 ,count(*)
from mytable
group by col1,col2
having count(*) > 1.
'''
but I have dozens of column in my table .... and using the above syntax is tedious to specify all the columns in the table.
trying another approach with select distinct ... will not identify for me the content of duplicated rows .
I tried somthing like
'''
select * , count (*)
from my table
group by *
'''
but that doesn't work.
Write a query which will write a query for you.
For example, "john smith" is a duplicate here:
SQL> select * from my_data order by 1;
FULL_NAME FIRST_NAME LAST_NAME
---------- -------------------- --------------------
h gonzalez h gonzalez
john smith john smith
john smith john smith
rudy chan rudy chan
Query uses user_tab_columns and aggregates all column names, concatenating them to the rest of a select statement:
SQL> SELECT 'select '
2 || LISTAGG (column_name, ', ') WITHIN GROUP (ORDER BY column_id)
3 || ', count(*) cnt '
4 || CHR (10)
5 || ' from '
6 || table_name
7 || CHR (10)
8 || ' group by '
9 || LISTAGG (column_name, ', ') WITHIN GROUP (ORDER BY column_id)
10 || CHR (10)
11 || ' having count(*) > 1;' statement_to_run
12 FROM user_tab_columns
13 WHERE table_name = 'MY_DATA'
14 GROUP BY table_name;
STATEMENT_TO_RUN
--------------------------------------------------------------------------------
select FULL_NAME, FIRST_NAME, LAST_NAME, count(*) cnt
from MY_DATA
group by FULL_NAME, FIRST_NAME, LAST_NAME
having count(*) > 1;
Now, copy/paste the above statement_to_run and get the result:
SQL> select FULL_NAME, FIRST_NAME, LAST_NAME, count(*) cnt
2 from MY_DATA group by
3 FULL_NAME, FIRST_NAME, LAST_NAME having count(*) > 1;
FULL_NAME FIRST_NAME LAST_NAME CNT
---------- -------------------- -------------------- ----------
john smith john smith 2
SQL>
Just write out all the columns.
there are dozens of columns ,about 30 , and there names look like : 'AGtrf-456F_RValue'
Copy-paste.
In SQL*Plus you can use the DESCRIBE command to describe a table and you can copy the column names from the table description.
Or you can list all the columns using:
SELECT '"' || column_name || '",'
FROM user_tab_columns
WHERE table_name = 'MY_DATA'
ORDER BY column_id;
And then copy-paste the output into your query into the SELECT and GROUP BY clauses.
Can you generate the query automatically.
Yes, but it usually is not worth it as it takes longer to write a query to generate the query than it does just to list the columns and copy-paste.
If you have lots of column names that require you to use quoted identifiers (i.e. they are mixed-case or use non-standard characters like -) then you can use:
SELECT EMPTY_CLOB()
|| 'SELECT '
|| LISTAGG('"' || column_name || '"', ',') WITHIN GROUP (ORDER BY column_id)
|| ', COUNT(1) FROM MY_DATA GROUP BY '
|| LISTAGG('"' || column_name || '"', ',') WITHIN GROUP (ORDER BY column_id)
|| ' HAVING COUNT(1) > 1;'
FROM user_tab_columns
WHERE table_name = 'MY_DATA'
ORDER BY column_id;
Which works unless you have too many columns and LISTAGG exceeds 4000 characters then you would need to use something like:
WITH columns (col, pos) AS (
SELECT '"' || column_name || '",',
column_id
FROM user_tab_columns
WHERE table_name = 'MY_DATA'
ORDER BY column_id
)
SELECT sql
FROM (
SELECT 'SELECT ' AS sql, 0 FROM DUAL
UNION ALL
SELECT col, pos FROM columns
UNION ALL
SELECT ' COUNT(1) FROM MY_DATA GROUP BY ', 10000 FROM DUAL
UNION ALL
SELECT col, 10000 + pos FROM columns
UNION ALL
SELECT '1 HAVING COUNT(1) > 1', 20000 FROM DUAL
ORDER BY 2
)
fiddle

CONCAT in Oracle SQL Developer

I don't know if I should use comma (,) or "||" as separator in CONCAT function for Oracle SQL.
This one works:
SELECT CONCAT(first_name, last_name) as name
FROM TABLE1
However, none of these below works out (I need to put a space between first_name and last_name, or to extract the initial letter from last_name and wrap this letter with parenthesis):
SELECT CONCAT(first_name || last_name) as name
FROM TABLE1
SELECT CONCAT(first_name || ' ' || last_name) as name
FROM TABLE1
SELECT CONCAT(first_name, ' ', last_name) as name
FROM TABLE1
SELECT CONCAT(first_name, '(', UPPER(STR(last_name, 1,1)), ')') as name
FROM TABLE1
Using double-pipe (||) instead of CONCAT in Oracle SQL is a more efficient way to go. Thanks to the comments that folks provided in here.
SELECT (first_name || ' ' || last_name)as name
FROM Table1;
Output:
John Smith
I also fixed the last script in the above question. Somehow it needs two right parentheses before "as name".
SELECT first_name || '(' || UPPER(SUBSTR(last_name, 1,1)) || ')')) as name, first_name, last_name
FROM TABLE1
Output:
John(S) John Smith

Concate columns using oracle SQL

C.ADDRESS1 || ',' || C.ADDRESS2 || ',' || C.ADDRESS3
pa.address_line_1,
pa.address_line_2,
pa.address_line_3 from per_addresses_f pa ;
how to join three column as single address column with oracle SQL concatenate
How to write query for joining 3 columns as single column?
You can write the concatenation as you've written it, but you have to make sure that all the components are strings. If some of them isn't, put it in TO_CHAR function. It's also good to put an alias to your result of concatenated columns:
SELECT C.ADDRESS1 || ',' || C.ADDRESS2 || ',' || C.ADDRESS3 as concatenated_adress
FROM your_table c
EDIT : After question was edited with concrete columns that are used, table name and with desired alias stated in question columns:
SELECT pa.address_line_1 || ',' || pa.address_line_2 || ',' || pa.address_line_3
as "Emergency Address"
FROM per_addresses_f pa
You can do this:
CONCAT(C.ADDRESS1, ',', C.ADDRESS2, ',', C.ADDRESS3) AS newColumnName
Try this :
SELECT firstname ||' '|| lastname AS employee_name FROM employee;
You can also try nested CONCAT assuming all address_line fields have char datatype:
SELECT CONCAT(CONCAT(CONCAT(pa.address_line_1,','),CONCAT(pa.address_line_2,',')),pa.address_line_3) AS address FROM per_addresses_f pa
But clearly pipe operator as suggested by #Goran Kutlaca is much simpler.
There are multiple ways to Concate the column in BIP.
1.
SELECT pa.address_line_1 || ',' || pa.address_line_2 || ',' ||
pa.address_line_3
as "Emergency Address" FROM per_addresses_f pa
2.
SELECT
CONCAT(CONCAT(CONCAT(pa.address_line_1,','),CONCAT(pa.address_line_2,',')),pa.address_line_3)
AS address FROM per_addresses_f pa
3.
select
CONCAT(pa.address_line_1,',',pa.address_line_2,',',pa.address_line_3)
as address FROM per_addresses_f pa

Concatenate with string but exclude when null

Oracle v11
Exclude a string in a Concat when the value is NULL?
Work
Query:
Select
*
LastName || ',' || FirstName AS Last_First_Name
--I've tried using NVL & NVL2
--NVL(LastName || ',' || FirstName,'') AS Last_First_Name2
FROM TableA
TableA
LastName FirstName ID
Smith Ann 1
2
Output I'm getting
LastName FirstName ID LastName_FirstName
Smith Ann 1 Smith,Ann
2 ,
Expected Output:
LastName FirstName ID LastName_FirstName
Smith Ann 1 Smith,Ann
2
Use CASE
Select *,
CASE WHEN LastName IS NOT NULL AND FirstName IS NOT NULL
THEN LastName || ',' || FirstName AS Last_First_Name
END lastname_firstname
FROM TableA
Something like this... I added simulated inputs to test all four possibilities. However, note that if you may have last name but no first name, and also first name but no last name, the combined column will show just one name but you will not know if it is first or last. (Also, when a comma is added, I also add a space after the comma, as is usual; that can be controlled easily though.)
with
tablea ( lastname, firstname, id ) as (
select 'Smith', 'Ann' , 1 from dual
union all select null , null , 2 from dual
union all select 'Ang' , null , 3 from dual
union all select null , 'Murat', 4 from dual
)
-- End of simulated inputs (for testing only, not part of the solution).
-- SQL query begins BELOW THIS LINE. Use your actual table and column names.
select lastname, firstname, id,
lastname
|| case when lastname is not null and firstname is not null then ', ' end
|| firstname
as last_first
from tablea
;
LASTNAME FIRSTNAME ID LAST_FIRST
---------- ---------- ---------- ------------
Smith Ann 1 Smith, Ann
2
Ang 3 Ang
Murat 4 Murat
One way is to use a CASE statement to conditionally add the comma:
CASE WHEN LastName IS NULL
THEN LastName || ','
ELSE NULL
END
|| FirstName AS Last_First_Name
Oracle supports NULLIF. If both first and last name are null, the result will just be , which can be filtered.
SELECT
NULLIF(LastName ||','|| FirstName, ',') AS FullName
FROM table
Alternately, if you need to allow for when a single name is populated, you can use TRIM to remove leading/trailing commas.
SELECT
TRIM(',', LastName ||','|| FirstName) AS FullName
FROM table
By analogy, you can do with anything, including names.
Consider the example address:
select
SUBSTR(
(CASE WHEN city is null THEN '' ELSE ', ' || city END) ||
(CASE WHEN street is null THEN '' ELSE ', ' || street END) ||
(CASE WHEN house is null THEN '' ELSE ', ' || house END) ||
(CASE WHEN addition is null THEN '' ELSE ', ' || addition END)
, 3) as address
from departments;
You can concatenate any number of fields with delimiters using:
SELECT REGEXP_REPLACE(REGEXP_REPLACE(Col1 || ',' || Col2 || ',' || Col3, ',,*', ','), '^,|,$', '')
The inner REGEXP_REPLACE removes repeated delimiters occurring when you have interior NULL values.
The outer REGEXP_REPLACE removes the leading and trailing delimiters occurring if your list of values starts or ends with NULL.
If all values are NULL, returns NULL.

format column headers during concat,oracle

I need to format column headers in the output of sql while using concat
Eg:
SELECT '' || to_char(sysdate,'ddmmyyyy') as DATE || ',' || ENO|| ',' || NAME|| ''
FROM EMP;
would retrieve me
ORA-00923: FROM keyword not found where expected.
Need the output as:
DATE ENO NAME
-----------------
251013 7560 RAM
251013 7561 ROSS
This format works
SELECT to_char(sysdate,'ddmmyyyy') || ',' || ENO || ',' || NAME as "DATE,ENO,NAME"
FROM EMP
but I have an issue with
ORA-00972: identifier is too long
when the length of column names inside as "" exceeds 30 characters
Eg:
SELECT to_char(sysdate,'ddmmyyyy') || ',' || ENO || ',' || NAME ||
',' || EMPLOYEE_IDENTIFICATION_NUMBER as "DATE,ENO,NAME,EMPLOYEE_IDENTIFICATION_NUMBER"
FROM EMP;
To achieve this output you have to build your query like this
SELECT to_char(sysdate,'ddmmyyyy') || ',' || ENO || ',' || NAME as "DATE,ENO,NAME" FROM EMP
You need to move the alias, if you really need it, at the end of the SELECT clause. Also the empty strings ('') can be removed:
SELECT to_char(sysdate,'ddmmyyyy') || ',' || ENO || ',' || NAME as DATE FROM EMP;