Selecting single column multiple times based on different conditions - sql

I have written a SQL query to retrieve required data and it looks like given below:
SELECT distinct p.person_id,p.birth_date,p.gender_code,
wm_concat(distinct r.race_code) as race_code,p.hispanic_latino_code,
c.clinically_diagnosed_code,
wm_concat(distinct c.characteristic_code) as chara_codes,
p.prev_adopted_code,p.age_adopted,
FIRST_VALUE(pe.removed_date) OVER (ORDER BY pe.removed_date),
count(pe.removed_date) as removal_count,
LAST_VALUE(pe.discharge_date) OVER (ORDER BY pe.discharge_date),
LAST_VALUE(pe.removed_date) OVER (ORDER BY pe.removed_date) as latest_removal_date,pe.created_date,
pe.removal_circumstance_code,wm_concat(distinct rr.removal_reason_code) as removal_reasons,
ps.placement_type_code,ps.icpc_placement_flag,pe.caretaker_structure_code
FROM PERSON p left outer join RACE r on p.person_id = r.person_id
left outer join CHARACTERISTIC c on c.person_id = p.person_id
left outer join PLACEMENT_EPISODE pe on p.person_id = pe.child_id
left outer join PLACEMENT_SETTING ps on p.person_id = ps.child_id
left outer join REMOVAL_REASON rr on pe.placement_episode_id = rr.placement_episode_id
GROUP BY p.person_id,p.birth_date,p.gender_code,p.hispanic_latino_code,
c.clinically_diagnosed_code,p.prev_adopted_code,p.age_adopted,pe.removed_date,
pe.discharge_date,pe.removed_date,pe.created_date,pe.removal_circumstance_code,
ps.placement_type_code,ps.icpc_placement_flag,pe.caretaker_structure_code
ORDER BY p.person_id
In the above mentioned query, I have already selected birth date for a person. Now again in select clause I want to select birth_date for persons with following condition:
condition 1: p.person_id = pe.primary_caretaker_id
condition 2: p.person_id = pe.secondary_caretaker_id
Can someone tell me the way to select these fields(birth_date based on two different conditions) in the existing query?
Birth_date has been already selected once for individual person. Now I want to retrieve birth_date for primary_caretaker and secondary_caretaker.

You will need to join to the PERSON table twice more:
SELECT distinct p.person_id,p.birth_date,p.gender_code,
wm_concat(distinct r.race_code) as race_code,p.hispanic_latino_code,
c.clinically_diagnosed_code,
wm_concat(distinct c.characteristic_code) as chara_codes,
p.prev_adopted_code,p.age_adopted,
FIRST_VALUE(pe.removed_date) OVER (ORDER BY pe.removed_date),
count(pe.removed_date) as removal_count,
LAST_VALUE(pe.discharge_date) OVER (ORDER BY pe.discharge_date),
LAST_VALUE(pe.removed_date) OVER (ORDER BY pe.removed_date) as latest_removal_date,
pe.created_date,
pe.removal_circumstance_code,wm_concat(distinct rr.removal_reason_code) as removal_reasons,
ps.placement_type_code,ps.icpc_placement_flag,pe.caretaker_structure_code,
primCare.birth_date as primary_carer_birth_date,
secCare.birth_date as secondary_carer_birth_date,
FROM PERSON p left outer join RACE r on p.person_id = r.person_id
left outer join PERSON primCare on primCare.person_id = pe.primary_caretaker_id
left outer join PERSON secCare on secCare.person_id = pe.secondary_caretaker_id
left outer join CHARACTERISTIC c on c.person_id = p.person_id
left outer join PLACEMENT_EPISODE pe on p.person_id = pe.child_id
left outer join PLACEMENT_SETTING ps on p.person_id = ps.child_id
left outer join REMOVAL_REASON rr on pe.placement_episode_id = rr.placement_episode_id
GROUP BY p.person_id,p.birth_date,p.gender_code,p.hispanic_latino_code,
c.clinically_diagnosed_code,p.prev_adopted_code,p.age_adopted,pe.removed_date,
pe.discharge_date,pe.removed_date,pe.created_date,pe.removal_circumstance_code,
ps.placement_type_code,ps.icpc_placement_flag,pe.caretaker_structure_code, primCare.birth_date, secCare.birth_date
ORDER BY p.person_id

Related

Check Specfic row with multiple rows in ORACLE

I want to select users list who is status is disabled for all application in username(ur_username table and that users should be active in Person Table(ur_person).
I tried with the following query :
select distinct E.PERSON_ID , E.DOMAIN_ID,e.first_name,e.last_name,e.type,E.username, E.SYSTEM_name from
(SELECT distinct p.person_id,p.domain_id,p.first_name,p.last_name,p.type,u.username, U.STATUS, U.SYSTEM_ID,s.system_name from ur_username u join
ur_username_person up on u.username_id=up.username_id
join ur_person p on up.person_id=p.person_id join ur_system s on u.system_id=s.system_id
WHERE p.status='ACTIVE') E WHERE E.person_id IN
( select distinct P.PERSON_ID from ur_username u join ur_username_person up on u.username_id=up.username_id
join ur_person p on up.person_id=p.person_id
where u.status='DISABLED')
I need to get the person list who is status is Disabled in all system in username Table as below image:
But instead I am getting person who is disable in one system but active in some other systems also:
You can get the person_ids using aggregation and having:
select p.person_id
from ur_username u join
ur_username_person up
on u.username_id = up.username_id join
ur_person p join
ur_system s
on u.system_id = s.system_id
where p.status = 'ACTIVE'
group by p.person_id
having max(u.status) = min(u.status) and max(u.status) ='DISABLED';
You specify that you want the persons, so this seems to answer your question. You can easily enhance this query to return more columns.

SQL join subquery where condition

How can I effectively subquery a LEFT OUTER JOIN so that only rows that meet a specific condition in the join are included?
I'd like to only count PPPD's where converted_at IS NULL. However when I add PPPD.converted_at IS NULL, then the result is more limited than I'd like it to be because it only includes patient_profiles that do have a row with null in converted_at. Instead I'd like a count of all PPPD records that have converted_at = null
SELECT P.id, P.gender, P.dob,
count(distinct recommendations.id) AS recommendation_count,
count(distinct PPPD.id) AS community_submissions,
FROM patient_profiles AS P
LEFT OUTER JOIN recommendations ON recommendations.patient_profile_id = P.id
LEFT OUTER JOIN patient_profile_potential_doctors AS PPPD ON PPPD.patient_profile_id = P.id
WHERE P.is_test = FALSE
GROUP BY P.id
You need to add the condition in the ON clause:
SELECT P.id, P.gender, P.dob,
count(distinct r.id) AS recommendation_count,
count(distinct PPPD.id) AS community_submissions,
FROM patient_profiles P LEFT OUTER JOIN
recommendations r
ON r.patient_profile_id = P.id LEFT OUTER JOIN
patient_profile_potential_doctors PPPD
ON PPPD.patient_profile_id = P.id AND PPPD.converted_at IS NULL
WHERE P.is_test = FALSE;
GROUP BY P.id

SQL two multi-row counts in one query

I have got two queries:
select m.name, count(distinct a.kursnr)
from trainer t
left outer join mitarbeiter m
on t.svnr = m.svnr
left outer join einzeltraining e
on t.svnr = e.trainer
left outer join abhaltung a
on t.svnr = a.trainer
group by m.name, t.svnr;
select m.name, count(e.trainer)
from trainer t
left outer join mitarbeiter m
on t.svnr = m.svnr
left outer join einzeltraining e
on e.trainer = t.svnr
group by m.name, e.trainer;
The first one returns the correct number of courses (kursnr) and the second number the correct number of individual classes (einzeltraining) hold by a trainer. However, I cannot make one SQL statement which shows both values in one table. Any help would be appreciated. Thank you.
While there is likely a more efficient way to do this, I wanted to show you the easy way to combine any two queries that share a common field such as this:
select coalesce(q2.name, q1.name) As Name, q1.KursnrCount, q2.TrainerCount
from
( --original first query
select m.name, count(distinct a.kursnr) as KursnrCount
from trainer t
left outer join abhaltung a
on t.svnr = a.trainer
left outer join mitarbeiter m
on t.svnr = m.svnr
left outer join einzeltraining e on svnr = e.trainer
group by m.name, t.svnr
) q1
full join
( --original second query
select count(e.trainer) as TrainerCount, m.name
from trainer t
left outer join einzeltraining e
on e.trainer = t.svnr
left outer join mitarbeiter m
on t.svnr = m.svnr
group by e.trainer, m.name
) q2 on q2.name = q1.name
You could also use an inner join or left join, instead of a full join, depending on how the name fields from those queries match up.

Select 1 record for multiple secondary join records

Have a query which selects 1 Lead for every associated person.
How can I group by Lead_ID + MAX(person.Created_Timestamp)
select
top 100 lead.lead_id,person.first_name,person.last_name,person.gender,person.modified_ts
from lead
left join person on person.lead_id=lead.lead_id
left join person_email on person_email.person_id=person.person_id
left join person_address on person_address.person_id=person.person_id
left join address_location on person_address.address_location_id=address_location.address_location_id
where address_location.state_code = 'QL'
select
lead.lead_id, MAX(person.Created_Timestamp)
from lead
left join person on person.lead_id=lead.lead_id
left join person_email on person_email.person_id=person.person_id
left join person_address on person_address.person_id=person.person_id
left join address_location on person_address.address_location_id=address_location.address_location_id
where address_location.state_code = 'QL'
GROUP BY lead.lead_id

What kind of SQL join would this be?

I need to go to two tables to get the appropriate info
exp_member_groups
-group_id
-group_title
exp_members
-member_id
-group_id
I have the appropriate member_id
So I need to check the members table, get the group_id, then go to the groups table and match up the group_id and get the group_title from that.
INNER JOIN:
SELECT exp_member_groups.group_title
FROM exp_members
INNER JOIN exp_member_groups ON exp_members.group_id = exp_member_groups.group_id
WHERE exp_members.member_id = #memberId
SELECT g.group_title
FROM exp_members m
JOIN exp_member_groups g ON m.group_id = g.group_id
WHERE m.member_id = #YourMemberId
If there is always a matching group, or you only want rows where it is, then it would be an INNER JOIN:
SELECT g.group_title
FROM exp_members m
INNER JOIN
exp_member_groups g
ON m.group_id = g.group_id
WHERE m.member_id = #member_id
If you want rows even where group_id doesn't match, then it is a LEFT JOIN - replace INNER JOIN with LEFT JOIN in the above.