Concat a string based on condition in oracle sql developer - oracle

I want to concat to the output based on condition. Here is my query:
select 'hey',
case id =1 then 'Mary' else 'Tom' end
from names;'
I want to print 'hey tom' or 'hey mary' based on id ... any help ??

It is concatenation you need; in Oracle, double pipe || represents that operator:
SQL> with names (id) as
2 (select 1 from dual union all
3 select 2 from dual union all
4 select 3 from dual
5 )
6 select id,
7 'hey ' || case when id = 1 then 'Mary'
8 else 'Tom'
9 end result
10 from names;
ID RESULT
---------- ----------
1 hey Mary
2 hey Tom
3 hey Tom
SQL>

You can run something like this query:
SELECT CONCAT('hey ', FIRST_NAME) from names where ID = '1';

Related

Extract Data Between Brackets in Oracle SQL

I have a table with data in below format
COURSE
[]
["12345"]
["12345","7890"
I want to extract the data between [] but without "
So, my output would be in below format
COURSE
12345
12345, 7890
I tried the below code which works fine for first 3 rows
select REGEXP_SUBSTR (COURSE,
'"([^"]+)"',
1,
1,
NULL,
1) from TEST;
But 4th row only results in 12345.
Why not simple translate?
SQL> with test (course) as
2 (select '[]' from dual union
3 select null from dual union
4 select '["12345"]' from dual union
5 select '["12345","7890"]' from dual
6 )
7 select course,
8 translate(course, 'a[]"', 'a') result
9 from test;
COURSE RESULT
---------------- -----------------------------------------
["12345","7890"] 12345,7890
["12345"] 12345
[]
SQL>

combine multiple rows result in single row based on one column value

I i want to combine multiple rows result into single row based on one column called type.
Ex say suppose i have below result from my query .
seqnum type name
456 SH Google2
456 CN transwork
123 SH partyshipper
123 CN consignee
Actual result i want is something like below table
seqnum consigneename shippername
456 transwork Google2
123 consignee partyshipper
Basically i want to get result like consignee name when type is CN and shipper name is when type is SH if its not both then i can add extra column with name just like otherparty.
I can get result and iterate result set and set value of object. but i think this will be better if we get formatted result in query only.can some one help in in getting this.
Thanks for the help.
Something like this usually helps; lines #1 - 7 represent your sample data. Code you need begins at line #8.
SQL> with test (seqnum, type, name) as
2 (select 456, 'SH', 'Google2' from dual union all
3 select 456, 'CN', 'transwork' from dual union all
4 select 123, 'SH', 'partyshipper' from dual union all
5 select 123, 'CN', 'consignee' from dual union all
6 select 999, 'XX', 'littlefoot' from dual
7 )
8 select seqnum,
9 max(case when type = 'CN' then name end) consigneename,
10 max(case when type = 'SH' then name end) shipppername,
11 max(case when type not in ('CN', 'SH') then name end) otherparty
12 from test
13 group by seqnum;
SEQNUM CONSIGNEENAM SHIPPPERNAME OTHERPARTY
---------- ------------ ------------ ------------
123 consignee partyshipper
999 littlefoot
456 transwork Google2
SQL>
Borrowing the query from #Littlefoot. You may also use PIVOT for this getting the expected result.
with test (seqnum, type, name) as
(select 456, 'SH', 'Google2' from dual union all
select 456, 'CN', 'transwork' from dual union all
select 123, 'SH', 'partyshipper' from dual union all
select 123, 'CN', 'consignee' from dual union all
select 999, 'OT', 'littlefoot' from dual
)
select * from test
pivot (
min(name) for type in
(
'SH' shippingname
, 'CN' consigneename
, 'OT' someother
)
)
;
SEQNUM SHIPPINGNAME CONSIGNEENAM SOMEOTHER
---------- ------------ ------------ ------------
999 littlefoot
456 Google2 transwork
123 partyshipper consignee
I'd self join the table and filter different types in each side of the join:
SELECT COALESCE(c.seqnum, s.seqnum) AS seqnum,
COALESCE(c.name, 'other') AS consigneename,
COALESCE(s.name, 'other') AS shippername
FROM (SELECT *
FROM mytable
WHERE type = 'CN') c
FULL OUTER JOIN (SELECT *
FROM mytable
WHERE type = 'SN') s ON c.seqnum = s.seqnum

count returns <<air>> when there's nothing to group by

Here's my SQL:
select
count(*)
from
sysdba.dw_cmap_arf_tmp
left join SYSDBA.TABLE1 rrc
on rrc.part_work_order = pwo
left join sysdba.TABLE2 R
on rrc.run_number = R.RUN_NUMBER
where
upper(run_type) like '%FEE%'
group by
pwo;
When there's nothing to group by, count returns --air--. It's null nor is it blank. I have modified the above SQL as the following to prove.
select
'>>' || count(*) || '<<' as blah
from
sysdba.dw_cmap_arf_tmp
left join SYSDBA.TABLE1 rrc
on rrc.part_work_order = pwo
left join sysdba.TABLE2 R
on rrc.run_number = R.RUN_NUMBER
where
upper(run_type) like '%ANNEAL%'
group by
pwo;
When I, however, write a statement above to perform an update, I got null. So tried coalesce, but got the same thing.
Does anyone know what I can do to replace --air-- with null or 0? Thanks!
P.S. I have did something research, but couldn't find anything...apologize in advance, if there's already a similar question out there.
Thanks!
This is what you currently have (based on Scott's EMP table): as there's no department 50, you get no rows selected (which is the air you're talking about, I presume).
SQL> with your_current_query as
2 (select count(*) cnt
3 from emp
4 where deptno = &deptno
5 group by job
6 )
7 select cnt
8 from your_current_query;
Enter value for deptno: 50
no rows selected
Just to show that it actually returns something if there are some data there:
SQL> /
Enter value for deptno: 30
CNT
----------
4
1
1
SQL>
OK; now, to do something with the situation where there are no rows selected, use union with a "dummy" row selected from the DUAL table:
SQL> with your_current_query as
2 (select count(*) cnt
3 from emp
4 where deptno = &deptno
5 group by job
6 )
7 select cnt
8 from your_current_query
9 -- add this: if YOUR_CURRENT_QUERY doesn't return anything, union it with
10 -- a select from dual
11 union all
12 select 0
13 from dual
14 where 0 = (select count(*) from your_current_query);
Enter value for deptno: 50
CNT
----------
0
SQL>
So: even though there are no employees in department 50, you got 0 as the result.
Again, to show what happens when there are some rows:
SQL> /
Enter value for deptno: 30
CNT
----------
4
1
1
SQL>
Finally, your query - rewritten - would look like this:
with your_current_query as
(select
count(*) cnt
from
sysdba.dw_cmap_arf_tmp
left join SYSDBA.TABLE1 rrc
on rrc.part_work_order = pwo
left join sysdba.TABLE2 R
on rrc.run_number = R.RUN_NUMBER
where
upper(run_type) like '%FEE%'
group by
pwo
)
select cnt from your_current_query
union all
select 0
from dual
where 0 = (select count(*) from your_Current_query);
See if it helps.

how to add different column with one code into one column?

id text
1 hi
1 how are u
1 fine ?
2 rad
2 qey
3
I am searching for a query where it can let me insert id = 1 to another table in one column
id test
1 hi how are you fine ?
2 rad qey
with the listagg function , i will have such result : hi how are you fine ? .. can i have it such
hi
how are u
fine ?
This query can be used to achieve your result:
WITH tab(id,text) AS (
SELECT 1, 'hi' FROM dual UNION ALL
SELECT 1, 'how are u' FROM dual UNION ALL
SELECT 1, 'fine ?' FROM dual UNION ALL
SELECT 2, 'rad' FROM dual UNION ALL
SELECT 2, 'qey' FROM dual UNION ALL
SELECT 3, NULL FROM dual)
-----
--End of data
-----
SELECT ID,
listagg(text, ' ') within GROUP (ORDER BY ROWNUM) AS text
FROM tab
GROUP BY ID;
Output
ID TEXT
1 hi how are u fine ?
2 rad qey
3
But there is one problem, although order by rownum is used but you cannot guaranty the order of text, its better to have one more column in your table that can define the order of the text as below
id text order_text
1 hi 1
1 how are u 2
1 fine ? 3
2 rad 1
2 qey 2
3 1
and the use the query as
SELECT ID,
listagg(text, ' ') within GROUP (ORDER BY order_text) AS text
FROM tab
GROUP BY ID;
You can try the LISTAGG function.
For more information, see here.

Oracle - How to return multi records from CASE

How to return multiple records from "CASE DEFAULT".
eg:
Master.COLUMN1 IN (CASE '#InputString'
WHEN 'One' THEN 1
WHEN 'Two' THEN 2
WHEN 'THREE' THEN 3
ELSE (SELECT NUM_BER FROM TABLE1 WHERE COLUMN2 LIKE '%#InputString%')
END)
I tried with passing One and it returns 1. But when I pass 'four' it showed error like ORA-01427 single-row sub query returns more than one row. How can i solve this??
you can try it like this:
column1 in (CASE '#InputString'
WHEN 'One' THEN 1
WHEN 'Two' THEN 2
WHEN 'THREE' THEN 3
END)
OR (column1 in (SELECT NUM_BER FROM TABLE1 WHERE COLUMN2 LIKE '%#InputString%')
and '#InputString' not in ('One', 'Two', 'THREE'));
Here is a sqlfiddle demo
You're getting the ORA-01427 error, because in select query in your else parts returns more than one row.
The below queries will help you:
WITH t AS
(SELECT 1 string FROM dual
UNION
SELECT 2 string FROM dual
UNION
SELECT 1234 string FROM dual
)
SELECT * FROM t
where t.string in ( case 'one' when 'one' then 1 else (select 1234 from dual) end);
output
_____
1
WITH t AS
(SELECT 1 string FROM dual
UNION
SELECT 2 string FROM dual
UNION
SELECT 1234 string FROM dual
)
SELECT * FROM t
where t.string in ( case 'two' when 'one' then 1 else (select 1234 from dual) end);
output
------
1234
You can use decode
SQL> ed
Wrote file afiedt.buf
1 with x as (
2 select 'A' as string from dual union all
3 select 'B' from dual union all
4 select 'C' from dual union all
5 select 'D' from dual
6 )
7 select string , decode(string, 'A',1,'B',2,3) as string_out
8* from x
SQL> /
S STRING_OUT
- ----------
A 1
B 2
C 3
D 3

Resources