Count Different Values in Oracle Using Outer Joins - oracle

My question is about left outer join with counter. I have two tables.
employee:
empid empname
----- -------
101 Tom
102 Jerry
103 Jack
104 Tim
allocation:
generator analyzer tester
--------- -------- ------
101 102 103
103 102 101
102 101 104
I need following result
empid empname generator analyzer tester
------ ------- --------- -------- -------
101 Tom 1 1 1
102 Jerry 1 2 0
103 Jack 1 0 1
104 Tim 0 0 1
I need to count the values of each task. Tom has generated 1, analyzed 1
and tested 1. Like that i need to count the values. Is this possible in
SQL. If this is possible please help me to get output.
I am getting the result. but it is not expected. I have used outer joins to solve the problem,
select
e.empid,
e.empname,
count(a1.generator),
count(a2.analyzer),
count(a3.tester)
from employee e
left join allocation a1
on e.empid=a1.author
left join allocation a2
on e.empid=a2.reviewer
left join allocation a3
on e.empid=a3.tester
group by
e.empid,
e.empname;

You can achieve it with this:
Select empid,sum(generaor),sum(analyzer),sum(tester)
from
(
Select empid,count(a.generaor) generaor,0 analyzer,0 tester
from employee
JOIN Allocation a on empid=a.generaor group by empid,a.generaor
UNION
Select empid,0 generaor,count(b.analyzer)analyzer,0 tester
from employee
JOIN Allocation b on empid=b.analyzer group by empid,b.analyzer
UNION
Select empid,0 generaor,0 analyzer,count(c.tester) tester
from employee
JOIN Allocation c on empid=c.tester group by empid,c.tester
) stag
group by empid

Try this
SELECT empid, empname, sum(generator), sum(analyzer), sum(tester) FROM
(SELECT e.empid, e.empname, count(a1.generator) generator, 0 analyzer, 0 tester
FROM Employee e
JOIN Allocation a1 ON a1.generator = e.empid
GROUP BY e.empname
UNION
SELECT e.empid, e.empname, 0 generator, count(a2.analyzer) analyzer, 0 tester
FROM Employee e
JOIN Allocation a2 ON a2.analyzer = e.empid
GROUP BY e.empname
UNION
SELECT e.empid, e.empname, 0 generator, 0 analyzer, count(a3.tester) tester
FROM Employee e
JOIN Allocation a3 ON a3.tester = e.empid
GROUP BY e.empname) tmp
GROUP BY empname
ORDER BY empid

Related

write function which will display train details having maximum passanger for given date?

following are the table in database.
many to many relations between train and passenger
table 1 name=train
TNO TNAMe
1 x
2 y
3 z
table 2 name=passenger
PNO PNAME
111 a
222 b
333 c
table 3 name=tp
TNO PNO TPDATE
1 111 23-NOV-15
2 222 24-JUN-14
3 222 19-JUN-13
1 333 23-NOV-15
using follwing code i only find out which train number has highest frequency
select tno,count(tno) as numberofoccurance from tp group by tno
Try to use group by and row_number analytical function as following:
Select name, tp_date
From
(Select t.tname tp.tp_date,
row_number() over (partition by tp.tp_date order by count(1) desc nulls last) as cnt
From train t
Join tp tp
On (t.id = tp.tno)
Group by tp.tno, tp.tp_date)
Where cnt = 1;
Cheers!!

How to return non-empty rows for a given ID - Hive

I have a table X
ID A B
--------------
1 abc 27
1 - 28
2 - 33
3 xyz 41
3 - 07
I need output as
ID A B
--------------
1 abc 27
2 - 33
3 xyz 41
I tried doing
max(A) OVER (PARTITION BY ID) as the_value
but it did not work. I can still see all the rows in the output table.
I was wondering if somebody has come across a similar situation and has a solution to this ?
you can use this simple trick for getting the full record for which some column is maxed:
select original.* from
(select ID,max(B) as B from Tbl group by ID ) maxB
inner join
(select * from Tbl ) original
on original.ID = maxB.ID and original.B = maxB.B
now this is of course an overkill code. you can also do:
select Tbl.* from
(select ID,max(B) as B from Tbl group by ID ) maxB
inner join
Tbl
on Tbl.ID = maxB.ID and Tbl.B = maxB.B
but the first version is more of a template to do whatever you want with further columns, fields, conditions joins etc.

Oracle aggregate functions on strings

I have an employee with multiple managers. The manager name field has (firstname,lastname) and the email field has(last.first#email.com).There is no Mgr id.
So, when I try to group this by employee id to get the max of Mgr name and email, some times I end up getting the wrong name/email id combination.
ex:
person Mgr_name Mgr_email
------- --------- ----------
111 brad,pitt pitt.brad#test.com
111 mike,clark clark.mike#test.com
when I group it by person and get the max(mgr_name),mgr_email, I get
person max(Mgr_name) max(Mgr_email)
------- --------- ----------
111 mike,clark pitt.brad#test.com
How do I get the correct email/name combination?
Use row_number analytical function instead:
with t(person ,Mgr_name , Mgr_email) as (
select 111 ,'brad,pitt' , 'pitt.brad#test.com' from dual union all
select 111 ,'mike,clark' , 'clark.mike#test.com' from dual )
select person ,Mgr_name , Mgr_email from (
select t1.*, row_number() over (order by mgr_name) num from t t1)
where num = 1
This get max mgr_name with correct email.
Output:
PERSON MGR_NAME MGR_EMAIL
---------- ---------- -------------------
111 brad,pitt pitt.brad#test.com
You could use a subselect to obtain the max mgr_name for each person in the table then join it back to the base results to limit to only display each persons "Max" manager...
SELECT t1.Person, t1.Mgr_name, t1.mgr_email
FROM tableName t1
INNER JOIN (Select max(mgr_name) mname, Person from TableName group by person) t2
on t1.mgr_name = t2.mname
and t2.Person = T1.Person

sql query to get the column data in one row

I have below data in a table called data_tab
sn code
2 101
2
2 202
5 103
5
5
How can i query to see result in one row, like
sn code1 code2 code3
2 101 202
5 103
Hi This gives the intented output ... take a look here
select sn,
max(decode(rn,1,code)) as CODE_1
,max(decode(rn,2,code)) as CODE_2
,max(decode(rn,3,code)) as CODE_3
from
(
select sn,
code,
row_number() over (partition by sn order by null ) rn
from test
)
group by sn

Is there a more efficient way to count the number of aggregate records in Oracle SQL?

I have more experience with MySQL and MSSQL but I don't consider myself a SQL expert.
I have a requirement for some SQL work running on an Oracle database. Not even sure the version yet but it should be somewhat recent (10, 11??).
Anyway, I have to count the number of distinct records that spans two tables. For sake of argument, let's call them master and detail.
The following SQL gives me the number I want against the data. However, this SQL will eventually be put in a UDF (or Oracle equivalent). But my question is, is there a better way? Either using some advanced Oracle optimization or even just a better SQL query.
Thanks
select count(*) from
(
select
mas.barcode
, det.barcode_val
from mas
inner join det on (det.trans_id = mas.trans_id and mas.trans_sub_id = det.trans_sub_id)
where
mas.trans_id = 12345
and det.code_type = 'COMMODORE'
group by
mas.barcode
, det.barcode_val
);
Data:
MAS
trans_id trans_sub_id barcode
-------------------------------------
12345 1 COM_A
12345 2 COM_A
12345 3 COM_B
DET
trans_id trans_sub_id code_type barcode_val
-------------------------------------------------------
12345 1 COMMODORE C64
12345 1 COMMODORE C64
12345 1 TANDY TRASH80
12345 2 COMMODORE C128
12345 2 ATARI 800XL
12345 2 COMMODORE AMIGA500
12345 3 COMMODORE C64
Results before count
--------------------
COM_A C64
COM_A C128
COM_A AMIGA500
COM_B C64
Results after count
-------------------
4
SELECT
COUNT(DISTINCT mas.barcode || det.barcode_val)
FROM mas
INNER JOIN det
ON (det.trans_id = mas.trans_id and mas.trans_sub_id = det.trans_sub_id)
WHERE
mas.trans_id = 12345
AND det.code_type = 'COMMODORE'
or
SELECT COUNT(*) FROM (
SELECT DISTINCT mas.barcode, det.barcode_val
FROM mas
INNER JOIN det
ON (det.trans_id = mas.trans_id and mas.trans_sub_id = det.trans_sub_id)
WHERE
mas.trans_id = 12345
AND det.code_type = 'COMMODORE'
)
If you use the
COUNT(DISTINCT mas.barcode || det.barcode_val)
make sure to put a delimiter between the pipeline:
COUNT(DISTINCT mas.barcode || '-' || det.barcode_val)
For example imagine the following scenario:
Column1 Column2 Column1 || Column2 Column1 || '-' || Column2
A B AB A-B
AB <null> AB AB-
1 201 1201 1-201
<null> 1201 1201 -1201
This table has 4 rows with 4 different values. But if you try a
COUNT(DISTINCT COLUMN1 || COLUMN2)
you would get just 2 "distinct" groups.
Just a tip to try to avoid those corner cases.

Resources