I have two tables like so:
table1(user, id, sex) table2(user, name, sex)
jjj 123 m jjj John m
jjj 124 m bbb Bob m
jjj 125 m ppp Pete f
bbb 126 m
bbb 127 f
ppp 128 f
ppp 129 m
ppp 130 m
I want result table where it displays all the users with their names and sex from table 2 who changed their sex at some point along with a count of how many users each name has. So this would be the result table:
(user, name, sex, count)
bbb Bob m 2
ppp Pete f 3
Currently im using this query:
select table2.user, table2.name, table2.sex, count(*)
from table1
join table2 on table1.user = table2.user
where table1.sex <> table2.sex
group by table2.user, table2.name, table2.sex
order by user
However the count column just counts from the resulting join table and not from original table1. Any ideas? thanks.
If I follow this correctly, one option use a lateral join and filtering:
select t2.*, t1.cnt
from table2 t2
inner join lateral (
select count(*) as cnt, min(sex) as minsex, max(sex) as maxsex
from table1 t1
where t1.user = t2.user
) t1 on t1.minsex <> t1.maxsex or t1.minsex <> t2.sex
Basically this filters table1 on users that have different sex or whose sex is different than in table2.
Related
Hi i have table1 and table2.
table1 is the logtime table of employees and table2 is the groupcode of the employee.
On table1 some employees has duplicate time in because they time in multiple time to just to secure their time in.
Table1
ID EMPID Time_IN
1 001 7:01 AM
2 004 7:04 AM
3 034 7:10 AM
4 034 7:11 AM
5 019 7:11 AM
6 019 7:12 AM
Table2
ID empID GroupName
1 001 AA
2 004 AB
3 034 AA
4 019 AA
result
GroupName CNT
AA 5
AB 1
Expected result
GroupName CNT
AA 3
AB 1
current query
Select b.GroupName, count(*) as cnt
from table1 a
inner join table2 b
on a.EMPID = b.empID
Group by b.GroupName
How can i achive as expected result above?
Thankyou in advance.
you can use distinct count as follows:
select t2.groupname, count(distinct empid) as cnt
from table1 t1 join table2 t2
on t1.empid = t2.empid
group by t2.groupname
The join is superfluous for the question you have asked:
select t2.GroupName, count(*) as cnt
from table2 t2
group by t2.GroupName;
This is much more efficient than joining and using count(distinct). You probably really have a different question, which should be asked as a new question.
Can you please help me with the query to find out the single record for the each student based on the subject.(Id,Name,subs are primary key). Ideally I will have 2 records for each subject. One with school TTT and MCC.
Table Structure:
StudentID StudentName Subject Marks School
1 AAA ENG 80 TTT
1 AAA ENG 80 MCC
1 AAA TAM 90 TTT
1 AAA TAM 90 MCC
2 BBB TAM 90 TTT
2 BBB TAM 90 MCC
3 CCC ENG 40 MCC
4 DDD ENG 95 MCC
5 EEE ENG 85 TTT
5 EEE ENG 85 MCC
I want the results
StudentID StudentName Subject Marks School
3 CCC ENG 40 MCC
4 DDD ENG 95 MCC
Here is one method using window functions:
select t.*
from (select t.*,
count(*) over (partition by studentid) as cnt
from t
) t
where cnt = 1;
This returns students with only one record. If you want student/subject combination with only one record, another method uses not exists:
select t.*
from t
where not exists (select 1
from t t2
where t2.studentid = t.studentid and
t2.subject = t.subject and
t2.school <> t.school
);
SELECT * FROM TABLEA A
WHERE EXISTS (SELECT STUDENTid, COUNT(1) TOTAL FROM TABLEA B
WHERE A.STUDENTID = B.STUDENTID
GROUP BY STUDENTID
HAVING COUNT(1) = 1)
This will give records to cases where there is no duplication of IDs
You can filter with a correlated subquery:
select t.*
from mytable t
where (select count(*) from mytable t1 where t1.studentid = t.studentid) = 1
I have a three tables
Table 1
Id Department
1 A
2 B
3 C
4 D
Table 2
Id DepartId Name
1 1 ABC
2 1 DEF
3 1 ASD
4 2 FGH
5 2 HJK
6 3 ZXC
Table 3
Id Depart Area
1 A pp
2 B
3 C nn
4 D oo
I need the result
Id Depart Name Area
1 A ABC pp
2 B FGH Null
3 C ZXC nn
4 D NULL oo
I need one matching entry from table 2 and table 3 to corresponding entry in the table 1
Do a left join to also get t1 rows without any reference in the t2 table. GROUP BY to get only 1 row per Department.
select t1.id, t1.Department, min(t2.Name)
from t1
left join t2 on t1.id = t2.DepartId
group by t1.id, t1.Department
I think I would do this with a correlated subquery:
select t1.*,
(select t2.name
from t2
where t1.id = t2.DepartId and rownum = 1
) as t2name
from t1;
This saves the overhead of an aggregation. An index on t2(DepartId, name) is optimal for this query.
by the way not the answer to your specific question but if instead of just one you want all the names you can use listagg
SELECT t1.id,
department,
LISTAGG (name, ',') WITHIN GROUP (ORDER BY name) names
FROM t1, t2
WHERE t1.id = t2.departId(+)
GROUP BY t1.id, department
ORDER BY 1
ID Department Names
1 A ABC,ASD,DEF
2 B FGH, HJK
3 C ZXC
4 D
If I want to display Order_Number data1 data2 data3 (most current by date changed OtherData1, OtherData2, OtherData3) date_changed the problem is I wasn't just one line, I was getting multiple lines for each order number.
What I would love to get is
1, a, f,q, cc,ccc,abc, 12/2/2014, bob
3, c, b,h, aa,aaa,abc, 12/2/2014, bob
Thanks!
I was working with
SELECT
t.Order_Number,
cr.data1, cr.data2, cr.data3,
t.OtherData1, t.OtherData2, t.OtherData3,
x.date_changed, cr.name
FROM
(SELECT
Order_Number,
Max(date_changed) as date_changed
FROM
table2
GROUP BY
Order_Number) x
JOIN
table2 t ON x.date_changed = t.date_changed
LEFT JOIN
table1 cr ON x.Order_Number = cr.Order_Number
WHERE cr.name = 'bob'
Here are example tables.
Table1:
Order_Number data1 data2 data3 name
1 a f q bob
2 b g g john
3 c b h bob
4 d s j john
Table2:
Order_Number date_changed OtherData1 OtherData2 OtherData3
1 11/30/2014 aa aaa abc
1 12/1/2014 bb bbb def
1 12/2/2014 cc ccc abc
3 12/1/2014 dd aaa def
2 11/30/2014 dd bbb abc
2 12/1/2014 ss ccc def
3 12/2/2014 aa aaa abc
4 11/26/2014 fc wer wsd
Your Join to config_log (Table2) needs to include the entire composite key if you want to retrieve unique rows.
JOIN
conf_log t ON x.date_changed = t.date_changed
And x.Order_Number = t.Order_number
I think you need to have 2 sub querys:
SELECT
Data.Order_Number,
Data.data1, Data.data2, Data.data3,
Data.OtherData1, Data.OtherData2, Data.OtherData3,
Data.date_changed, Data.name
FROM
(SELECT
Order_Number,
Max(date_changed) as date_changed
FROM
table2
GROUP BY
Order_Number) x
JOIN (SELECT
t.Order_Number,
cr.data1, cr.data2, cr.data3,
t.OtherData1, t.OtherData2, t.OtherData3,
t.date_changed, cr.name
FROM table2 t
JOIN table1 cr
ON t.Order_Number = cr.Order_Number) AS Data
ON x.date_changed = data.date_changed
AND x.Order_Number = data.Order_number
WHERE cr.name = 'bob'
The fact that you had cr.name in the where clause means the LEFT JOIN had the same affect as just JOIN.
I have three tables:
tbl_trans
trans_id volume
a 10
b 20
c 30
tbl_primary_id
trans_id primary_id
a QQQ
b b
c RRR
tbl_name
trans_id name
a Billy
QQQ Tom
b Lizzy
RRR Peter
I need to join the name column from tbl_name to tbl_trans. A straight inner join won't work because I need primary_id as an intermediary to return this:
trans_id tbl_name.trans_id volume name
a QQQ 10 Tom
a QQQ 10 Billy
b b 20 Lizzy
c RRR 30 Peter
What's the best way to do this? I was using a subquery but wasn't sure if there was a more direct statement.
(Side note: None of this is my schema. I can't modify the design in any way, unfortunately.)
just 2 joins
select tt.trans_id, tn.trans_id, tt.volume, tn.name
from tbl_trans tt
inner join tbl_primary_id tti on tti.trans_id = tt.trans_id
inner join tbl_name tn on tn.trans_id = tti.primary_id
by the way, your column naming is a little bit weird : primary_id in tbl_primary_id is related with trans_id in tbl_name
oh, seems I missed something :
select tt.trans_id as tid, tti.primary_id as tid2, tt.volume, tn.name
from tbl_trans tt
inner join tbl_primary_id tti on tti.trans_id = tt.trans_id
inner join tbl_name tn on tn.trans_id = tti.primary_id or tn.trans_id = tti.trans_id
see sqlfiddle