How to group columns based on specific text and sum them using ORACLE database - sql

I am a newbie in oracle. Trying to group columns based on a specific text and sum other columns.
let's say I have below tables
I want to group by all people with the last name. Like below
I have no clue how should I proceed.
Note: There could be multiple names but I just want to filter for Sharma, Decosta and Liver.
Updating the question.
Sorry for updating the question. but in a real scenario search string is not always at last.
Let me give you another example.
Output.

The queries offered so far does seem to work to get what you need. But the below does:
With inputs as
(
select 'Rahul Kumar Sharma' as Name, 10 as No_of_beer_bottles from dual union all
select 'Rohith Kumar Sharma' as Name, 5 as No_of_beer_bottles from dual union all
select 'Sharma' as Name, 20 as No_of_beer_bottles from dual union all
select 'Rahul Kumar Varma' as Name, 10 as No_of_beer_bottles from dual
)
select SUBSTR(name,Instr(name,' ',-1)+1) as Name, sum(No_of_beer_bottles) as No_of_beer_bottles
from inputs
group by SUBSTR(name,Instr(name,' ',-1)+1);
Output:

You can use regexp_substr():
select regexp_substr(name, '[^ ]+$') as last_name, sum(num_beers)
from t
group by regexp_substr(name, '[^ ]+$');

If you use have a table with all the words you are searching for (or define them in a Common Table Expression like I did below), you can join on that search term then sum the numeric column.
Query 1
WITH
search_words (word)
AS
(SELECT 'Sharma' FROM DUAL
UNION ALL
SELECT 'Decosta' FROM DUAL
UNION ALL
SELECT 'Liver' FROM DUAL),
d (name, num_beers)
AS
(SELECT 'Ravi Sharma', 1 FROM DUAL
UNION ALL
SELECT 'Sam Decosta', 4 FROM DUAL
UNION ALL
SELECT 'Jhony Liver', 5 FROM DUAL
UNION ALL
SELECT 'Ravi Sharma', 2 FROM DUAL
UNION ALL
SELECT 'Rohul Sharma', 3 FROM DUAL
UNION ALL
SELECT 'Jhon Decosta', 3 FROM DUAL
UNION ALL
SELECT 'V Decosta', 3 FROM DUAL)
SELECT sw.word, SUM (d.num_beers) AS total_beer
FROM search_words sw, d
WHERE INSTR (UPPER (d.name), UPPER (sw.word)) > 0
GROUP BY sw.word;
Result 1
WORD TOTAL_BEER
__________ _____________
Decosta 10
Sharma 6
Liver 5
Query 2
WITH
search_words (word)
AS
(SELECT 'Pen' FROM DUAL
UNION ALL
SELECT 'Dog' FROM DUAL),
d (name, quantity)
AS
(SELECT 'Ravi have red pens', 2 FROM DUAL
UNION ALL
SELECT 'Sam''s grifriend have black dogs', 4 FROM DUAL
UNION ALL
SELECT 'Jhony has blue pen', 1 FROM DUAL
UNION ALL
SELECT 'Ravi has white dog', 1 FROM DUAL
UNION ALL
SELECT 'Rahul has small dogs', 3 FROM DUAL
UNION ALL
SELECT 'There are pens inside Jhon''s car', 3 FROM DUAL
UNION ALL
SELECT 'My dog and me are flying.', 1 FROM DUAL)
SELECT sw.word, SUM (d.quantity) AS total_quantity
FROM search_words sw, d
WHERE INSTR (UPPER (d.name), UPPER (sw.word)) > 0
GROUP BY sw.word;
Result 2
WORD TOTAL_QUANTITY
_______ _________________
Dog 9
Pen 6

Related

Is there a reason I am getting no rows selected for this NOT IN nested query

Query:
SELECT teamid
FROM team
WHERE teamid NOT IN (SELECT team_teamid FROM gymnast);
Tables:
TEAM table
Gymnast table
I have been trying to figure this out for a while, any information would be greatly appreciated. Thank you!
The fiddle for oracle
val NOT IN (some list) means the value does NOT match every entry in the list.
But if one entry in the list is null, value <> null can never be true for that entry, which means the entire NOT IN expression can never be true.
See the following examples:
WITH team (teamid) AS (
SELECT 1 FROM DUAL UNION
SELECT 2 FROM DUAL UNION
SELECT 3 FROM DUAL UNION
SELECT 4 FROM DUAL
)
, gymnast (team_teamid) AS (
SELECT 1 FROM DUAL UNION
SELECT 2 FROM DUAL UNION
SELECT 2 FROM DUAL UNION
SELECT 4 FROM DUAL
)
SELECT teamid FROM team WHERE teamid NOT IN (SELECT team_teamid FROM gymnast)
;
Result:
TEAMID
3
Case 2 with nulls in the list:
WITH team (teamid) AS (
SELECT 1 FROM DUAL UNION
SELECT 2 FROM DUAL UNION
SELECT 3 FROM DUAL UNION
SELECT 4 FROM DUAL
)
, gymnast (team_teamid) AS (
SELECT 1 FROM DUAL UNION
SELECT 2 FROM DUAL UNION
SELECT null FROM DUAL UNION
SELECT 4 FROM DUAL
)
SELECT teamid FROM team WHERE teamid NOT IN (SELECT team_teamid FROM gymnast)
;
Result:
TEAMID
No rows in result, due to the gymnast with a null team_teamid.

How to count distinct flags in the sql

BELOW IS SNIPPET OF MY DATA
Here is the sample creation code of testing.
CREATE TABLE MYGROUP ( Category,PERSON,Flag ) AS
SELECT 'Cat1','A','1' FROM DUAL
UNION ALL SELECT 'Cat1','A','0' FROM DUAL
UNION ALL SELECT 'Cat1','A','1' FROM DUAL
UNION ALL SELECT 'Cat1','B','1' FROM DUAL
UNION ALL SELECT 'Cat1','B','0' FROM DUAL
UNION ALL SELECT 'Cat2','A','0' FROM DUAL
UNION ALL SELECT 'Cat2','A','0' FROM DUAL
UNION ALL SELECT 'Cat2','A','0' FROM DUAL
UNION ALL SELECT 'Cat2','B','1' FROM DUAL
UNION ALL SELECT 'Cat2','B','1' FROM DUAL
UNION ALL SELECT 'Cat2','B','0' FROM DUAL
UNION ALL SELECT 'Cat3','X','0' FROM DUAL
UNION ALL SELECT 'Cat3','Y','0' FROM DUAL;
Desired Output:
Category - Count of Distinct Persons with Flag = 1
Cat1 - 2
Cat2 - 1
Cat3 - 0
I need to get my code in Big query to get distinct counts of persons. It shouldnt double count.
You can use conditional aggregation
SELECT
Category,
COUNT(DISTINCT CASE WHEN Flag = 1 THEN PERSON END)
FROM MYGROUP
GROUP BY Category;

sql query for like to Order exact match at top in list

sql query for like to show exact match first in list:
dataset: "abcd", "a","b","bc","bcd"
select * from table where data like "%bc%";
it should show in order bc, abcd, bcd.
As you said - sort by match.
SQL> with test (col) as
2 (select 'abcd' from dual union all
3 select 'a' from dual union all
4 select 'b' from dual union all
5 select 'bc' from dual union all
6 select 'bcd' from dual
7 )
8 select col
9 from test
10 where col like '%' || '&&par_search_string' ||'%'
11 order by utl_match.jaro_winkler_similarity(col, '&&par_search_string') desc;
Enter value for par_search_string: bc
COL
----
bc
bcd
abcd
SQL> undefine par_search_string
SQL> /
Enter value for par_search_string: cd
COL
----
bcd
abcd
SQL>
One of many methods:
with
t as (
select 'abcd' c from dual union all
select 'a' from dual union all
select 'b' from dual union all
select 'bc' from dual union all
select 'bcd' from dual
)
select *
from t
where c like '%bc%'
order by length(c)
Demo.
I think you can use a query like this one that can return your expected result.
select * from table where data='bc'
union all
select * from table where data like '%bc%' and data<>'bc'
One method is:
select *
from t
where data like '%bc%'
order by (case when data = 'bc' then 1 else 2 end);
Or if you don't want to type so much:
order by nullif(data, 'bc') desc
The descending sort puts NULL values first.

How to upside down the result rows of a select statment in oracle?

I can select a list of rows from a table. but I want to show them by swapping upside down.
Explaination:
with table1 as
(
select 1 ID, 'txt1' value from dual
union all
select 2, 'txt2' from dual
union all
select 7, 'txt7' from dual
union all
select 5, 'txt5' from dual
union all
select 3, 'txt3' from dual
)
select * from table1;
in above query I can obtain following result
ID | VALUE
------------------
1 txt1
2 txt2
7 txt7
5 txt5
3 txt3
but I want to show them as follows
ID | VALUE
------------------
3 txt3
5 txt5
7 txt7
2 txt2
1 txt1
How to do that?
One approach would be to add a computed column to your set of union queries, then order by that column:
WITH table1 AS (
SELECT 1 ID, 'txt1' value, 1 AS position FROM dual
UNION ALL
SELECT 2, 'txt2', 2 FROM dual
UNION ALL
SELECT 7, 'txt7', 3 FROM dual
UNION ALL
SELECT 5, 'txt5', 4 FROM dual
UNION ALL
SELECT 3, 'txt3', 5 FROM dual
)
SELECT *
FROM table1
ORDER BY pos DESC;
Note that there is no internal order to a SQL table in general. Actually, even the current ordering you are observing is not necessarily guaranteed by Oracle. If you expect a certain order in a result set, you need to impose it via a ORDER BY clause.
How's this?
with table1 as
(
select 1 ID, 'txt1' value from dual
union all
select 2, 'txt2' from dual
union all
select 7, 'txt7' from dual
union all
select 5, 'txt5' from dual
union all
select 3, 'txt3' from dual
)
select * from table1 order by rownum desc;
Actually this is not working for this perticular example. but it is working for normal table.

Select values is a row as column values

How can I retrieve values in a row as column values?
Example:
Consider the output of below query as INPUT :
Select 1,2,3,4,5,6,7,8,9,10
from dual;
I need a query that can give below output:
COL1
----
1
2
3
4
5
6
7
8
9
10
SELECT 1 AS "COL1" FROM dual
UNION
SELECT 2 FROM dual
UNION
SELECT 3 FROM dual
UNION
SELECT 4 FROM dual
UNION
SELECT 5 FROM dual
UNION
SELECT 6 FROM dual
UNION
SELECT 7 FROM dual
UNION
SELECT 8 FROM dual
UNION
SELECT 9 FROM dual
UNION
SELECT 10 FROM dual ;
If you want to generate a sequence of numbers in Oracle:
with n as (
select level as n
from dual
connect by level <= 10
)
select *
from n;
Or, if you have 10 columns, you can do an unpivot. An easy way is with union all:
select col1 from t union all
select col2 from t union al
. . .
select col10 from t;