Concat values with group by in Oracle - oracle

My table Students is like
Id Name Dept
---------------
2 Ball A
3 Cat B
1 Dog C
2 Egg C
3 Fox D
4 Gun A
1 Hen B
1 Apple A
Now I want to get result as
Dept Names
-------------------
A Apple,Ball,Gun
B Hen,Cat
C Dog,Egg
D Fox
And here concatenation should be done based on the ascending order of Id column.
I have tried using wm_concat(), xmlagg(xmlelement()) functions but concatenation not follwing column Id order.
My Database version is Oracle 10.2.0.5.0
Thank You

Try ordering the values first on a subquery then using the wm_concat later. I've tested it on my workstation and it work fine. Couldn't create an sqlfiddle because it won't let me use the wm_concat function
select dept, wm_concat(name) from
(
select id, name, dept
from test
order by dept, id, name
) group by dept

Try with WM_CONCAT Function,
SELECT dept, WM_CONCAT(name) names
FROM(
SELECT dept, name
FROM students
order by name
)
GROUP BY dept
ORDER BY dept;

Related

How to get distinct rows based on selected columns instead of all columns of a table in Oracle

I am trying to get first distinct 3 columns while the last column can have any value. If i do distinct on all columns then it gives me 8 rows. This table is dynamic so i will need distinct 3 columns and any value in the last column.
I have the following scenerio,
Name Surname Road Pet
John Trav John_road dog
Kaley Couco Couco_road horse
Charlie Sheen Sheen_road rabbit
Johnny Galecki Galecki_road cat
John Trav John_road donkie
Kaley Couco Couco_road mouse
Charlie Sheen Sheen_road goat
Johnny Galecki Galecki_road pig
Desired result:
Name Surname Road Pet
John Trav John_road dog
Kaley Couco Couco_road mouse
Charlie Sheen Sheen_road rabbit
Johnny Galecki Galecki_road cat
I tried the solution on this link but it is not working:
Oracle 11g SQL to get unique values in one column of a multi-column query
Please help in Oracle
As you don't care about the last column value, a simple option is to aggregate it as
select name, surname, road, max(pet)
from your_table
group by name, surname, road
Use row_number() with partition by first three columns:
dbfiddle demo
select *
from (
select t.*,
row_number() over (partition by Name, Surname, Road order by pet) rn
from t)
where rn = 1
Did you try this
SELECT NAME, SURNAME, rOAD, PET FROM
(
SELECT NAME, SURNAME, rOAD, PET, ROW_NUMBER () OVER (PARTITION BY NAME, SURNAME, rOAD ORDER BY PET) RN FROM FROM TABLE_NAME
) WHERE RN=1

how to find the table row count in hive query using group by

Here my question: I have a table with some records like (name, date, type). Suppose I have three type a, b and c.Now I want to count percentage of each type mean COUNT(type)/COUNT(table row count)??
select type,COUNT(type) as counttype,counttype/(select COUNT(*) from xyz) from xyz group by xyz;
"(select COUNT(*) from xyz)" this giving me error.
How to find the table Row Count?
You can use below query :-
select A.type,A.type_cnt,(A.type_cnt/B.total_cnt) from
(Select type,count(type) as type_cnt from xyz group by type)A
JOIN
(select count(*)as total_cnt from xyz)B
ON 1=1;
Without JOIN it is much faster, using analytic function:
select type,
count(type) as type_cnt,
count(type)/count(*) over() as pct
from xyz
group by type;

How to reduce join operation to a single row in Oracle?

This example is invented for the purpose of the question.
SELECT
PR.PROVINCE_NAME
,CO.COUNTRY_NAME
FROM
PROVINCE PR
JOIN COUNTRY CO ON CO.COUNTRY_ID=PR.COUNTRY_ID
WHERE
PR.PROVINCE_ID IN (1,2)
Let's assume that COUNTRY_ID is not the Primary Key in the Country table and the above join on Country table returns potentially multiple rows. We don't know how many rows and we don't care why there are multiple ones. We only want to join on one of them, so we get one row per Province.
I tried subquery for the join but can't pass in PR.COUNTRY_ID for Oracle 11.2. Are there any other ways that this can be achieved?
A typical safe approach of handling tables without PK is to extend the duplicated column with a unique index (row_numer of the duplicated row)
In your case this would be:
with COUNTRY_UNIQUE as (
select COUNTRY_ID,
row_number() over (partition by COUNTRY_ID order by COUNTRY_NAME) rn,
COUNTRY_NAME
from country)
select * from COUNTRY_UNIQUE
order by COUNTRY_ID, rn;
leading to
COUNTRY_ID RN COUNTRY_NAME
---------- ---------- ------------
1 1 C1
2 1 C2
2 2 C3
The combination of COUNTRY_IDand RN is unique, so if you constraint only RN = 1 the COUNTRY_ID is unique.
You may define the order of the duplicated records and control with it the selection - in our case we choose the smalest COUNTRY_NAME.
The whole join used this subquery and constraints the countries on RN = 1
with COUNTRY_UNIQUE as (
select COUNTRY_ID,
row_number() over (partition by COUNTRY_ID order by COUNTRY_NAME) rn,
COUNTRY_NAME
from country)
SELECT
PR.PROVINCE_NAME
,CO.COUNTRY_NAME
FROM
PROVINCE PR
JOIN COUNTRY_UNIQUE CO ON CO.COUNTRY_ID=PR.COUNTRY_ID
WHERE
PR.PROVINCE_ID IN (1,2)
AND CO.RN = 1; /* consider only unique countries */
If you have Oracle 12c, you can use a LATERAL view in the join. Like this:
SELECT
PR.PROVINCE_NAME
,CO.COUNTRY_NAME
FROM
PROVINCE PR
CROSS JOIN LATERAL (
SELECT * FROM COUNTRY CO
WHERE CO.COUNTRY_ID=PR.COUNTRY_ID
FETCH FIRST 1 ROWS ONLY) CO
WHERE
PR.PROVINCE_ID IN (1,2)
Update for Oracle 11.2
In Oracle 11.2, you can use something along these lines. Depending on the size of COUNTRY and how many duplicates there are per COUNTRY_ID, it could perform as well or better than the 12c approach. (Fewer buffer gets but more memory required).
SELECT pr.province_name,
co.country_name
FROM province pr
INNER JOIN (SELECT *
FROM (SELECT co.*,
ROW_NUMBER () OVER (PARTITION BY co.country_id ORDER BY co.country_name) rn
FROM country co)
WHERE rn = 1) co
ON co.country_id = pr.country_id
WHERE pr.province_id IN (1, 2)

How to use the union operator in oracle

I know that the union operator is used to (for example) return all rows from two tables after eliminating duplicates. Example:
SELECT a_id
FROM a
UNION
SELECT b_id
FROM b;
The result of listing of all elements in A and B eliminating duplicates is {1,2,3,4,5,6,7,8}.
If you joined A and B you would get only {4,5}. You would have to perform a full outer join to get the full list of 1-8. My question is if I wanted to use the union operator to display from a table called employees, the employee_id and job_id ( employee id being a number data type, and job_id being a VARCHAR2 data type) How would I go about doing this?
Would it be something like this: This does not run in oracle obviously,
SELECT employee_id
UNION
SELECT job_id
FROM employees;
If you really wanted to union together all the EMPLOYEE_IDs followed by all the JOB_IDs you'd use
SELECT TO_CHAR(EMPLOYEE_ID) FROM EMPLOYEES
UNION ALL
SELECT JOB_ID FROM EMPLOYEES
If you had rows with EMPLOYEE_IDs of 1, 2, and 3, and those same rows had JOB_IDs of 1, 11, and 111 you'd get a result set of six rows with a single column which would have values of
1
2
3
1
11
111
By using UNION ALL Oracle will allow the duplicates to pass through.
Share and enjoy.

HiveQL UNION ALL

I have table_A:
id var1 var2
1 a b
2 c d
Table_B:
id var1 var2
3 e f
4 g h
All I want is table, combined:
id var1 var2
1 a b
2 c d
3 e f
4 g h
This is my .hql:
CREATE TABLE combined AS
SELECT all.id, all.var1, all.var2
FROM (
SELECT a.id, a.var1, a.var2
FROM table_A a
UNION ALL
SELECT b.id, b.var1, b.var2
FROM table_B b
) all;
I'm coding straight from page 112 of Programming Hive by Edward Capriolo, et al.
The error I get, no matter what ostensibly reasonable variation of the above that I try, is
cannot recognize input near '.' 'id' ',' in select expression.
I have tried using AS between the table name and the alias, asterisks since I want everything from both tables. Same error. I've tried other things and gotten other errors... All I want to do is UNION two tables. (I've tried UNION instead of UNION ALL — same error).
Just replace all with another word. It seems to be a reserved keyword. E.g:
CREATE TABLE combined AS
SELECT unioned.id, unioned.var1, unioned.var2
FROM (
SELECT a.id, a.var1, a.var2
FROM table_A a
UNION ALL
SELECT b.id, b.var1, b.var2
from table_B b
) unioned;
I have similar query working. Just changing table name and column names. Try this. Hope this helps you.
create table new_table as
select
distinct
id, name
FROM
table1
union all
select
distinct
id,name
from
table2
;
Try this, it worked for me.
CREATE TABLE combined AS
SELECT id, var1, var2
FROM (
SELECT id, var1, var2
FROM table_A
UNION ALL
SELECT id, var1, var2
from table_B
) a;

Resources