SQL join with union - sql

Cant understand what is the problem the union query works just fine if run it without join but i need to use it inside left join. And when I try it shows me the error that says that column DisplayName used more than once. What im doing wrong?
LEFT JOIN (
SELECT
p.Id,
zvl.DisplayName,
dlz.DisplayName
FROM
cm.Projects p
LEFT JOIN cm.ProjectVisualBlocks pvb ON pvb.ProjectId= p.Id
JOIN DBL.[Bl_2b987e3e-4939-e711-80c8-000d3af7ae73] b ON pvb.Id = b.ProjectVisualBlockId
LEFT JOIN cm.Participants [User] ON [User].Id= b.[4a789414-4a39-e711-80c8-000d3af7ae73]
LEFT JOIN cm.Participants [User_A] ON [User_A].Id= b.[4c789414-4a39-e711-80c8-000d3af7ae73]
WHERE
p.ProjectTypeId= '526ba5f2-4c39-e711-80c8-000d3af7ae73'
UNION
SELECT
p.Id,
zvl.DisplayName,
dlz.DisplayName
FROM
cm.Projects p
LEFT JOIN (
SELECT
pp.Id,
d.DisplayName
FROM
cm.Projects pp
LEFT JOIN cm.ProjectVisualBlocks pvb ON pvb.ProjectId= pp.Id
JOIN cm.ProjectLines pl ON pvb.Id = pl.ProjectVisualBlockId
JOIN DBL.[Ln_F1CC2727-45C5-E711-80C2-0CC47A966E25] ln ON ln.ProjectLineId = pl.Id
AND ln.ProjectVisualBlockId = pvb.Id
JOIN cm.Participants d ON d.Id= ln.[F2CC2727-45C5-E711-80C2-0CC47A966E25]
) dlz ON dlz.Id= p.Id
LEFT JOIN (
SELECT
p.Id,
[User].DisplayName
FROM
cm.Projects p
LEFT JOIN cm.ProjectVisualBlocks pvb ON pvb.ProjectId= p.Id
JOIN cm.ProjectLines pl ON pvb.Id = pl.ProjectVisualBlockId
JOIN DBL.[Ln_A25439AA-B51B-E811-80C2-0CC47A966E25] l ON l.ProjectLineId = pl.Id
AND l.ProjectVisualBlockId = pvb.Id
JOIN cm.Participants [User] ON [User].Id= l.[F0CC2727-45C5-E711-80C2-0CC47A966E25]
) zvl ON zvl.Id= p.Id
WHERE
p.ProjectTypeId= 'b498aad9-3ec5-e711-80c2-0cc47a966e25'
) xavdol ON xavdol.Id= p.Id

you have used column DisplayName twice, change to this:
LEFT JOIN (
SELECT
p.Id,
zvl.DisplayName,
dlz.DisplayName as DisplayName2
FROM
cm.Projects p
LEFT JOIN cm.ProjectVisualBlocks pvb ON pvb.ProjectId= p.Id
JOIN DBL.[Bl_2b987e3e-4939-e711-80c8-000d3af7ae73] b ON pvb.Id = b.ProjectVisualBlockId
LEFT JOIN cm.Participants [User] ON [User].Id= b.[4a789414-4a39-e711-80c8-000d3af7ae73]
LEFT JOIN cm.Participants [User_A] ON [User_A].Id= b.[4c789414-4a39-e711-80c8-000d3af7ae73]
WHERE
p.ProjectTypeId= '526ba5f2-4c39-e711-80c8-000d3af7ae73'
UNION
SELECT
p.Id,
zvl.DisplayName,
dlz.DisplayName as DisplayName2
FROM
cm.Projects p
LEFT JOIN (
SELECT
pp.Id,
d.DisplayName
FROM
cm.Projects pp
LEFT JOIN cm.ProjectVisualBlocks pvb ON pvb.ProjectId= pp.Id
JOIN cm.ProjectLines pl ON pvb.Id = pl.ProjectVisualBlockId
JOIN DBL.[Ln_F1CC2727-45C5-E711-80C2-0CC47A966E25] ln ON ln.ProjectLineId = pl.Id
AND ln.ProjectVisualBlockId = pvb.Id
JOIN cm.Participants d ON d.Id= ln.[F2CC2727-45C5-E711-80C2-0CC47A966E25]
) dlz ON dlz.Id= p.Id
LEFT JOIN (
SELECT
p.Id,
[User].DisplayName
FROM
cm.Projects p
LEFT JOIN cm.ProjectVisualBlocks pvb ON pvb.ProjectId= p.Id
JOIN cm.ProjectLines pl ON pvb.Id = pl.ProjectVisualBlockId
JOIN DBL.[Ln_A25439AA-B51B-E811-80C2-0CC47A966E25] l ON l.ProjectLineId = pl.Id
AND l.ProjectVisualBlockId = pvb.Id
JOIN cm.Participants [User] ON [User].Id= l.[F0CC2727-45C5-E711-80C2-0CC47A966E25]
) zvl ON zvl.Id= p.Id
WHERE
p.ProjectTypeId= 'b498aad9-3ec5-e711-80c2-0cc47a966e25'
) xavdol ON xavdol.Id= p.Id
sql
sql-server

Related

JOIN two SELECT without UNION

It needs to download the ID, name and surname of those who have registered by the deadline and have an identity card (with the relevant conditions) or passport (with the relevant conditions). ID card and passport are two separate tables.
I have made the SQL queries in UNION format and it works:
select distinct p.id, p.name, p.surname from persons.person p
join persons.documents d on d.person_id = p.id
join persons.id_card idd on d.id_card_id = idd.id
join persons.id_card_to_registration ir on idd.id = ir.id_card
join registrations.registration r on ir.registration_id = r.id
where p.created_at >= '2022-01-01'
and p.created_at <= '2022-03-30'
and p.registration_id = r.id
and ir.status in (0,5)
UNION
select distinct p.id, p.name, p.surname from persons.person p
join persons.documents d on d.person_id = p.id
join persons.passport pass on d.passport_id = pass.id
join persons.passport_country pc on pc.id = pass_country_id
join persons.passport_to_registration pr on pass.id = pr.passport_id
join registrations.registration r on pr.registration_id = r.id
where p.created_at >= '2022-01-01'
and p.created_at <= '2022-03-30'
and p.registration_id = r.id
and pc.zone in (0,1) or (pc.zone is null and pass.safe = true);
I would now like to do this SQL in one query without union and unfortunately it doesn't work for me - I tried to do it like this:
select distinct p.id, p.name, p.surname from persons.person p
join persons.documents d on d.person_id = p.id
left join persons.id_card idd on d.id_card_id = idd.id
left join persons.id_card_to_registration ir on idd.id = ir.id_card
left join persons.passport pass on d.passport_id = pass.id
left join persons.passport_country pc on pc.id = pass_country_id
left join persons.passport_to_registration pr on pass.id = pr.passport_id
join registrations.registration r on ir.registration_id = r.id
where p.created_at >= '2022-01-01'
and p.created_at <= '2022-03-30'
and p.registration_id = r.id
and (ir.status in (0,5) or ir.status is null)
and pc.zone in (0,1) or (pc.zone is null and pass.safe = true)
And it doesn't return any records to me. I would like some advice on what error I have made. And is it possible to create such a query without union?
The SQL in clause may help to filter by each condition. This may be the way to avoid the union clause, please let me know if this works for you:
select distinct p.id, p.name, p.surname from persons.person p
where p.created_at >= '2022-01-01'
and p.created_at <= '2022-03-30'
and ((p.id in
(select distinct p2.id from persons.person p2
d.person_id from persons.documents d on d.person_id = p2.id
join persons.id_card idd on d.id_card_id = idd.id
join persons.id_card_to_registration ir on idd.id = ir.id_card
join registrations.registration r on ir.registration_id = r.id
where p2.registration_id = r.id
and ir.status in (0,5)
)
) or (
(p.id in
(select distinct p3.id from persons.person p3
d.person_id from persons.documents d on d.person_id = p3.id
join persons.passport pass on d.passport_id = pass.id
join persons.passport_country pc on pc.id = pass_country_id
join persons.passport_to_registration pr on pass.id = pr.passport_id
join registrations.registration r on pr.registration_id = r.id
where p3.registration_id = r.id
and pc.zone in (0,1) or (pc.zone is null and pass.safe = true);
)
)
))
I think you'll have better performance if you can convert the query to use EXISTS.
SELECT DISTINCT p.id, p.name, p.surname
FROM persons.person p
WHERE p.created_at >= '2022-01-01'
AND p.created_at <= '2022-03-30'
AND(EXISTS (SELECT *
FROM persons.documents d
JOIN persons.id_card idd
ON d.id_card_id = idd.id
JOIN persons.id_card_to_registration ir
ON idd.id = ir.id_card
JOIN registrations.registration r
ON ir.registration_id = r.id
WHERE p.id = d.person_id
AND p.registration_id = r.id
AND ir.status IN (0,5))
OR EXISTS (SELECT *
FROM persons.documents d
JOIN persons.passport pass
ON d.passport_id = pass.id
JOIN persons.passport_country pc
ON pc.id = pass_country_id
JOIN persons.passport_to_registration pr
ON pass.id = pr.passport_id
JOIN registrations.registration r
ON pr.registration_id = r.id
WHERE p.id = d.person_id
AND p.registration_id = r.id
AND pc.zone IN (0,1)
OR (pc.zone IS NULL
AND pass.safe = TRUE)))

Why does adding this field make my query run slow?

The query below runs in less than a second if I take off one field from the select list -- the last one, att. But having it there causes the query to take over a minute. Any thoughts? Note that the subquery inside the left join runs fast on its own.
select p.person_id, cfm.family_id, p.nick_name, p.last_name, s.lookup_value as group_role, gm.active, g.group_id, g.group_name,
g.active as group_active, tg.category, gc.cluster_name, coalesce(a.attendance,0) as att --this field is the culprit
from smgp_group g
join smgp_group_cluster gc on g.group_cluster_id = gc.group_cluster_id
join smgp_member gm on g.group_id = gm.group_id
join core_person p on gm.person_id = p.person_id
join core_family_member cfm on p.person_id = cfm.person_id
join core_lookup s on gm.role_luid = s.lookup_id
join #target_groups tg on g.group_id = tg.group_id
left join (
select at.person_id, goc.group_id, count(at.attended) as attendance from core_occurrence_attendance at
join core_occurrence o on at.occurrence_id = o.occurrence_id
join smgp_group_occurrence goc on o.occurrence_id = goc.occurrence_id
where goc.group_id in (select group_id from #target_groups)
and o.occurrence_start_time between #start_date and #end_date
group by at.person_id, goc.group_id
) a on p.person_id = a.person_id and g.group_id = a.group_id
where tg.category = 'adults' or (tg.category = 'kids' and s.lookup_value in ('Leader-Teacher','Assistant Leader'))
Try running the following -
SELECT p.persON_id, cfm.family_id, p.nick_name,
p.last_name, s.lookup_value as group_role,
gm.active, g.group_id, g.group_name,
g.active as group_active, tg.cATegory,
gc.cluster_name, a.ATtendance
INTO #tempDataset
FROM smgp_group g
JOIN smgp_group_cluster gc
ON g.group_cluster_id = gc.group_cluster_id
JOIN smgp_member gm
ON g.group_id = gm.group_id
JOIN core_persON p
ON gm.persON_id = p.persON_id
JOIN core_family_member cfm
ON p.persON_id = cfm.persON_id
JOIN core_lookup s
ON gm.role_luid = s.lookup_id
JOIN #target_groups tg
ON g.group_id = tg.group_id
LEFT JOIN (SELECT AT.persON_id, goc.group_id, count(AT.ATtended) as ATtendance FROM core_occurrence_ATtendance AT
JOIN core_occurrence o
ON AT.occurrence_id = o.occurrence_id
JOIN smgp_group_occurrence goc
ON o.occurrence_id = goc.occurrence_id
WHERE goc.group_id IN (SELECT group_id
FROM #target_groups)
AND o.occurrence_start_time BETWEEN #start_dATe AND #end_dATe
GROUP BY AT.persON_id, goc.group_id) a
ON p.persON_id = a.persON_id
AND g.group_id = a.group_id
WHERE tg.cATegory = 'adults' or (tg.cATegory = 'kids' AND s.lookup_value IN ('Leader-Teacher','Assistant Leader'))
SELECT persON_id,
family_id,
nick_name,
last_name,
group_role,
active,
group_id,
group_name,
group_active,
cATegory,
cluster_name,
coalesce(ATtendance,0) AS ATT
FROM #tempDataset
If that runs slowly, you can possibly add an index on the temp table, but I would try doing the above as a first step.
The query below runs in 3 seconds and resolved the problem. Thanks.
select at.person_id, goc.group_id, count(at.attended) as attendance
into #a
from core_occurrence_attendance at
join core_occurrence o on at.occurrence_id = o.occurrence_id
join smgp_group_occurrence goc on o.occurrence_id = goc.occurrence_id
where goc.group_id in (select group_id from #target_groups)
and o.occurrence_start_time between #start_date and #end_date
group by at.person_id, goc.group_id
select p.person_id, cfm.family_id, p.nick_name, p.last_name, s.lookup_value as group_role, gm.active, g.group_id, g.group_name,
g.active as group_active, tg.category, gc.cluster_name, coalesce(#a.attendance,0) as att--, --this field is the culprit
from smgp_group g
join smgp_group_cluster gc on g.group_cluster_id = gc.group_cluster_id
join smgp_member gm on g.group_id = gm.group_id
join core_person p on gm.person_id = p.person_id
join core_family_member cfm on p.person_id = cfm.person_id
join core_lookup s on gm.role_luid = s.lookup_id
join #target_groups tg on g.group_id = tg.group_id
left join #a on p.person_id = #a.person_id and g.group_id = #a.group_id
where tg.category = 'adults' or (tg.category = 'kids' and s.lookup_value in ('Leader-Teacher','Assistant Leader'))

Nested query WHERE procedure code IN and AND

Would like to take the following Query and alter it so that it brings back ONLY records where each patient (based on MRN) has BOTH ProcedureCodeList IN ('115-1','117-1','311-1') AND ProcedureCodeList = '119-103'
SELECT P.SiteID, O.ProcedureCodeList, P.MRN, PINFO.LastName, PINFO.FirstName, PINFO.[State] AS Species, PINFO.City AS Breed, O.ProcedureDescList, RF.FieldName, RF.FieldValue, R.ContentText
, R.LastSignDate
FROM ReportFinding RF
INNER JOIN Report R
ON RF.ReportID = R.ReportID
INNER JOIN [Order] O
ON R.ReportID = O.ReportID
INNER JOIN Visit V
ON O.VisitID = V.VisitID
INNER JOIN Patient P
ON P.PatientID = V.PatientID
INNER JOIN PersonalInfo PINFO
ON P.PersonalInfoID = PINFO.PersonalInfoID
WHERE
O.ProcedureCodeList IN ('115-1','117-1','119-103')
ORDER BY R.LastSignDate DESC
There are a couple of ways to solve this. One way is to create two subqueries and join them on the MRN.
SELECT a.SiteID, a.ProcedureCodeList, a.MRN, a.LastName, a.FirstName, a.Species, a.Breed, a.ProcedureDescList, a.FieldName, a.FieldValue, a.ContentText, a.LastSignDate
FROM
(SELECT P.SiteID, O.ProcedureCodeList, P.MRN, PINFO.LastName, PINFO.FirstName, PINFO.[State] AS Species, PINFO.City AS Breed, O.ProcedureDescList, RF.FieldName, RF.FieldValue, R.ContentText, R.LastSignDate
FROM ReportFinding RF
INNER JOIN Report R ON RF.ReportID = R.ReportID
INNER JOIN [Order] O ON R.ReportID = O.ReportID
INNER JOIN Visit V ON O.VisitID = V.VisitID
INNER JOIN Patient P ON P.PatientID = V.PatientID
INNER JOIN PersonalInfo PINFO ON P.PersonalInfoID = PINFO.PersonalInfoID
WHERE O.ProcedureCodeList IN ('115-1','117-1','119-103')) as a
JOIN
(SELECT P.MRN
FROM [Order]
INNER JOIN Visit V ON O.VisitID = V.VisitID
INNER JOIN Patient P ON P.PatientID = V.PatientID
WHERE O.ProcedureCodeList = '119-103') as b ON a.MRN = b.MRN
ORDER BY a.LastSignDate
The PersonalInfo table is not needed in the second query. I don't think ReportFinding and Report are either, based on your JOINs. It depends on what these tables are actually doing.
Another way starts with the original query and adds the following to the WHERE clause (before the ORDER BY):
AND P.MRN IN
(SELECT P.MRN
FROM [Order]
INNER JOIN Visit V ON O.VisitID = V.VisitID
INNER JOIN Patient P ON P.PatientID = V.PatientID
WHERE O.ProcedureCodeList = '119-103')
I would look at the execution plans of both solutions to know which is the better one in this case.

Subquery in from clause, Invalid Identifier in Where clause

select * from iiasa_inventory.inv_device d
join iiasa_inventory.inv_type ty on d.type_id = ty.id
join iiasa_inventory.inv_category c on ty.category_id = c.id
join iiasa_inventory.inv_device_2_barcode b on b.device_id = d.id
join iiasa_inventory.inv_barcodes bc on b.barcode_id = bc.id
join iiasa_inventory.inv_status s on d.status = s.id
join iiasa_inventory.inv_brand br on ty.brand_id = br.id
left join iiasa_inventory.inv_supplier su on su.id = d.supplier_id
left join iiasa_inventory.inv_supplier sup on sup.id = d.maintenance_with
left join (select distinct device_id from
iiasa_inventory.inv_device_2_persons_cc) dp
on dp.device_id = d.id
where dp.active = 1
I am trying to select my data but the where-clause says that "dp.active" is an INVALID Identifier. This is probably because the table dp is in the subquery. I have tried to give it an alias name and some other things I found while browsing stackoverflow, but I cant seem to find a solution. Any idea?
This is Oracle PL/SQL.
Put the check for active = 1 in the subquery as shown below.
select * from iiasa_inventory.inv_device d
join iiasa_inventory.inv_type ty on d.type_id = ty.id
join iiasa_inventory.inv_category c on ty.category_id = c.id
join iiasa_inventory.inv_device_2_barcode b on b.device_id = d.id
join iiasa_inventory.inv_barcodes bc on b.barcode_id = bc.id
join iiasa_inventory.inv_status s on d.status = s.id
join iiasa_inventory.inv_brand br on ty.brand_id = br.id
left join iiasa_inventory.inv_supplier su on su.id = d.supplier_id
left join iiasa_inventory.inv_supplier sup on sup.id = d.maintenance_with
left join (select distinct device_id from iiasa_inventory.inv_device_2_persons_cc where active = 1) dp on dp.device_id = d.id
That is because you are not selecting active column in dp.
select * from iiasa_inventory.inv_device d
join iiasa_inventory.inv_type ty on d.type_id = ty.id
join iiasa_inventory.inv_category c on ty.category_id = c.id
join iiasa_inventory.inv_device_2_barcode b on b.device_id = d.id
join iiasa_inventory.inv_barcodes bc on b.barcode_id = bc.id
join iiasa_inventory.inv_status s on d.status = s.id
join iiasa_inventory.inv_brand br on ty.brand_id = br.id
left join iiasa_inventory.inv_supplier su on su.id = d.supplier_id
left join iiasa_inventory.inv_supplier sup on sup.id = d.maintenance_with
left join (select distinct device_id,active from iiasa_inventory.inv_device_2_persons_cc) dp on dp.device_id = d.id
where dp.active = 1
OR you can just filter from the subquery itself. Like:
left join (select distinct device_id
from iiasa_inventory.inv_device_2_persons_cc
where active=1) dp on dp.device_id = d.id

SQL use nested select in middle of inner join

Is it possible to use a select in the middle of joining...
I am trying to do the following:
FROM
tblorders o
INNER JOIN tblunits u on o.id = u.orderid
INNER JOIN ((SELECT
,Min(n.date) as [MinDate]
from tblNotes n
Where n.test = 'test') te
INNER JOIN tblnotes n on te.id = n.id
and te.[MinDate] = n.AuditinsertTimestamp)
INNER Join tblClient c ON o.ClientId = c.Id
Basically in the select in the middle of the query it is selecting only the notes with min date. The problem is I need to do this here because I need from tblOrders to be the first table.......
Suggestions?
The INNER JOIN failed because you have a leading comma here:
,Min(n.date) as [MinDate]
I think you are looking for something like this:
SELECT ...
FROM tblorders o
INNER JOIN tblunits u on o.id = u.orderid
INNER JOIN (
SELECT id, Min(date) as [MinDate]
from tblNotes
Where test = 'test'
group by id
) te <-- not sure what JOIN clause to use here, please post schema
INNER JOIN tblnotes n on te.id = n.id
and te.[MinDate] = n.AuditinsertTimestamp
INNER Join tblClient c ON o.ClientId = c.Id
You are missing an alias and join condition:
FROM
tblorders o
INNER JOIN tblunits u on o.id = u.orderid
INNER JOIN ((SELECT Min(n.date) as [MinDate]
from tblNotes n
Where n.test = 'test') te
INNER JOIN tblnotes n on te.id = n.id
and te.[MinDate] = n.AuditinsertTimestamp)
-- missing
AS z
ON <join conditions haere>
INNER Join tblClient c ON o.ClientId = c.Id
Yes, you can have a Select in a Join.