SQL Count condition in main Query - sql

I want to pick on those who for the column is_initial_event: the values can be 0 or 1. I only want those who have only 1. Not that they have both 1 and 0. There are multiple detail rows for is_initial_event.
select ac.Full_name, pe.program_start_date, pe.program_end_date, tp.approved_by_Description as
Approved, ev.is_initial_event, tp.staff from all_clients_view ac
inner join program_enrollment_expanded_view pe
on ac.people_id = pe.people_id
inner join service_plan_goals_objectives_methods_view tp
on ac.people_id = tp.people_id
inner join service_plan_event_view ev
on ac.people_id = ev.people_id
where pe.program_name = 'CFTSS' and tp.Approved_by_description is null
Here I tried to add in the count, what I want to count is that if the people_id has > 0 for ev.Is_initial_event = 1 and also has > when ev.IS_initial_event = 0, then I don't want that people_id only when it only has records where ev.is_initial_event = 1 not both.

Are you looking for window functions?
select *
from (
select
ac.Full_name,
pe.program_start_date,
pe.program_end_date,
tp.approved_by_Description as Approved,
ev.is_initial_event,
tp.staff,
min(ev.is_initial_event) over(partition by ac.people_id) min_initial_event
from all_clients_view ac
inner join program_enrollment_expanded_view pe
on ac.people_id = pe.people_id
inner join service_plan_goals_objectives_methods_view tp
on ac.people_id = tp.people_id
inner join service_plan_event_view ev
on ac.people_id = ev.people_id
where
pe.program_name = 'CFTSS'
and tp.Approved_by_description is null
) t
where min_initial_event = 1
This returns rows for which all rows having the same people_id have initial_event set to 1 (note that this assumes that this column contains only 0s and 1s, as explained in your question).

Related

T-SQL Full Outer Join (sample provided)

I have some issues getting a full outer join to work in T-SQL. The left outer join part seems to be working okay, but the right outer join doesn't work as expected. Here's some sample data to test this on:
I have a table A with the following columns and data. The row marked with red is the row that cannot be found in table B.
And a second table B with the following columns and data. The rows marked with yellow are the rows that cannot be found in table A.
I am trying to join the tables using the following sql code:
select tableA.klientnr, tableA.uttakstype, tableA.uttaksnr, tableA.vareanr TableAItem,tableB.vareanr tableBitem, tableA.kvantum tableAquantity, tableB.totkvant tableBquantity
from tableA as tableA
full outer join tableB as tableB on tableA.klientnr=tableB.klientnr and tableA.uttakstype=tableB.uttakstype and tableA.uttaksnr=tableB.uttaksnr and tableA.vareanr=tableB.vareanr and tableB.IsDeleted=0
where tableA.UttaksNr=639779 and tableA.IsDeleted=0
The result of the sql is the following image. The row marked in red is the extra row from tableA that does show up, but I can't get the rows from table B to show up
Expected to have 2 extra rows
550 SA 639779 NULL 100059 NULL 0
550 SA 639779 NULL 103040 NULL 14
Later edit:
Would this be correct way to handle the full outer join where there's the header/line type of structure? Or can the query be optimized?
SELECT ISNULL(q1.accountid, q2.accountid) AccountId
,ISNULL(q1.klientnr, q2.klientnr) KlientNr
,ISNULL(q1.tilgangstype, q2.tilgangstype) 'Reception Type'
,ISNULL(q1.tilgangsnr, q2.tilgangsnr) 'Reception No'
,ISNULL(q1.dato, q2.dato) dato
,ISNULL(q1.LevNr, q2.LevNr) LevNr
,ISNULL(q1.Pakkemerke, q2.Pakkemerke) Pakkemerke
,ISNULL(q1.VareANr, q2.VareANr) VareANr
,ISNULL(q1.Ankomstdato,q2.Ankomstdato) 'Arrival Date'
,q1.Antall1
,q1.totkvant1
,q1.Antall2
,q1.totkvant2
,q2.Antall
,q2.totkvant
,q2.AntallTilFrys
,q2.TotKvantTilFrys
,ISNULL(q1.EksternKommentar1,q2.EksternKommentar1) EksternKommentar1
,q2.[Last Upsert]
FROM (
SELECT w700.accountid
,w700.klientnr
,w700.tilgangstype
,w700.tilgangsnr
,w700.dato
,w700.Ankomstdato
,w700.LevNr
,w700.pakkemerke
,w789.VareANr
,sum(IIF(w789.prognosetype = 1, w789.Antall, NULL)) AS Antall1
,sum(IIF(w789.prognosetype = 1, w789.totkvant, NULL)) AS totkvant1
,sum(IIF(w789.prognosetype = 2, w789.Antall, NULL)) AS Antall2
,sum(IIF(w789.prognosetype = 2, w789.totkvant, NULL)) AS totkvant2
,w700.EksternKommentar1
FROM trading.W789Prognosekjopstat AS w789
INNER JOIN trading.W700Tilgangshode AS w700 ON w700.AccountId = w789.AccountId
AND w700.KlientNr = w789.Klientnr
AND w700.Tilgangsnr = w789.Tilgangsnr
AND w700.Tilgangstype = w789.Tilgangstype
AND w700.IsDeleted = 0
WHERE w789.IsDeleted = 0
GROUP BY w700.accountid
,w700.klientnr
,w700.tilgangstype
,w700.tilgangsnr
,w700.dato
,w700.Ankomstdato
,w700.LevNr
,w700.pakkemerke
,w789.VareANr
,w700.EksternKommentar1
) q1
FULL OUTER JOIN (
SELECT w700.accountid
,w700.klientnr
,w700.tilgangstype
,w700.tilgangsnr
,w700.dato
,w700.Ankomstdato
,w700.LevNr
,w700.pakkemerke
,w702.VareANr
,w702.Antall
,w702.TotKvant
,w702.ValPris
,w702.AntallTilFrys
,w702.TotKvantTilFrys
,w700.EksternKommentar1
,(SELECT MAX(LastUpdateDate) FROM (VALUES (w702.createdAt),(w702.updatedAt)) AS UpdateDate(LastUpdateDate)) AS 'Last Upsert'
FROM trading.w702PrognoseKjop w702
INNER JOIN trading.W700Tilgangshode AS w700 ON w700.AccountId = w702.AccountId
AND w700.KlientNr = w702.Klientnr
AND w700.Tilgangsnr = w702.Tilgangsnr
AND w700.Tilgangstype = w702.Tilgangstype
AND w700.IsDeleted = 0
WHERE w702.IsDeleted = 0
) q2 ON q1.accountid = q2.accountid
AND q1.klientnr = q2.klientnr
AND q1.tilgangstype = q2.tilgangstype
AND q1.tilgangsnr = q2.tilgangsnr
AND q1.vareanr = q2.vareanr
WHERE totkvant1 IS NOT NULL
OR totkvant2 IS NOT NULL
OR totkvant IS NOT NULL
Filtering with full join is really tricky. Your where criteria are actually turning the full join into a left join.
You can do what you want by filtering before the join:
select a.klientnr, a.uttakstype, a.uttaksnr, a.vareanr a.tableAitem,
b.vareanr b.tableBitem, a.kvantum a.tableAquantity, b.totkvant b.tableBquantity
from (select a.*
from tableA a
where a.UttaksNr = 639779 and a.IsDeleted = 0
) a full join
(select b.*
from tableB b
where b.IsDeleted = 0
) b
on a.klientnr = b.klientnr and
a.uttakstype= b.uttakstype and
a.uttaksnr = b.uttaksnr and
a.vareanr = b.vareanr;

Return only results that match more than 2 conditions

How do I only return results if more than two values from a list are found?
For example, if they don't have at least three of the following codes attached to their account then don't include them:
I13.0
I13.2
I20.0
I20.1
I20.8
I20.9
I21.01
I21.02
I21.09
I21.11
I21.19
I21.21
I21.29
I21.3
I21.4
I21.9
I21.A1
I21.A9
I22.0
Do I just need to put having count(distinct PROB.ICD10DiagnosisCode) > 2 after the group statement? I am getting results but I want to make sure I am not taking the long way around the bus.
SELECT DISTINCT
PER.ID AS PatientID,
IORG.OrganizationMRN AS PatientMRN
FROM works..Problem PROB (nolock)
JOIN works..Problem_Encounter PROBENC ON PROB.ID = PROBENC.ProblemID
JOIN works..Encounter ENC ON PROBENC.EncounterID = ENC.ID
JOIN works..patient_member PM ON ENC.PatientID = PM.ID
JOIN works..Document ON Document.EncounterID = ENC.ID
JOIN works..DocumentEvent
ON Document.documentid = DocumentEvent.documentid
JOIN works..Person PER ON Document.PatientID = PER.ID
JOIN works..Patient_Iorg IORG
ON PER.ID = IORG.PersonID and IORG.InternalOrganization = 3
WHERE PROB.ProblemStatusDE IN (9)
AND PROB.RecordedDTTM > DATEADD(month,-6,GETDATE())
AND PROB.ICD10DiagnosisCode IN
(
SELECT ICD10DiagnosisCode
FROM CVCReports.dbo.rptPETEligibleICD10
)
AND PM.IsDeceasedFLAG = 'N'
AND DocumentEvent.documenteventde NOT IN (18)
AND Document.Status LIKE 'Final%'
AND Document.DocumentTypeDE NOT IN (288)
AND ENC.DTTM > DATEADD(year,-2,GETDATE())
GROUP BY OrganizationMrn, PER.ID
having count(distinct PROB.ICD10DiagnosisCode) > 2

Nesting Queries to get multiple column results

Have two queries , one collects moves in based on property and unit type the other would collect based on Move Outs for the same data. when ran separately they yield the correct information (move outs are 6 and move ins are 11) Have tried nesting in select and from statements but not getting what i need. When nested within the select am getting the correct move outs per unit type, but each line for move ins is total move ins. I recall that the nesting here would only return one value but know there is a way to return the value for each row. Any assistance is appreciated.
SELECT
p.scode as PropNumber,
p.saddr1 propname,
ut.scode as UnitType,
COUNT(t.hmyperson) as Moveouts,
(
SELECT COUNT(t.hmyperson) as MoveIns
FROM
tenant t
JOIN unit u ON t.hunit = u.hmy
JOIN property p ON p.hmy = u.hproperty
JOIN unittype ut ON ut.hmy = u.HUNITTYPE
WHERE
t.dtmovein >= getdate() - 14
AND p.scode IN ('gsaff')
) mi
FROM
Property p
JOIN unit u ON u.hproperty = p.hmy
JOIN tenant t ON t.hunit = u.hmy
JOIN unittype ut ON ut.hmy = u.HUNITTYPE
WHERE
p.scode IN ('gsaff')
AND t.DTMOVEOUT >= getdate()- 14
GROUP BY
ut.scode,
p.scode,
p.saddr1
With this data is coming out like :
PropNumber Propname UnitType MoveOuts MoveIns
1 x tc2 1 11
1 x tc3 2 11
1 x tc4 1 11
1 x tc5 1 11
1 x tc6 1 11 <pre>
Move in column should display as
2
5
1
0
3
You need to correlate the subquery according to the record being processed in the outer query. This also requires that you use different table aliases in the subquery than in the outer query.
It is hard to tell without seeing sample data, however I would expect that you need to correlate with all non-aggregated columns in the outer query.
Try changing :
(
SELECT COUNT(t.hmyperson) as MoveIns
FROM
tenant t
JOIN unit u ON t.hunit = u.hmy
JOIN property p ON p.hmy = u.hproperty
JOIN unittype ut ON ut.hmy = u.HUNITTYPE
WHERE
t.dtmovein >= getdate() - 14
AND p.scode IN ('gsaff')
) mi
To :
(
SELECT COUNT(t.hmyperson) as MoveIns
FROM
tenant t1
JOIN unit u1 ON t1.hunit = u1.hmy
JOIN property p1 ON p1.hmy = u1.hproperty
JOIN unittype ut1 ON ut1.hmy = u1.HUNITTYPE
WHERE
t1.dtmovein >= getdate() - 14
AND p1.scode IN ('gsaff')
AND p1.scode = p.scode
AND p1.saddr1 = p.saddr1
AND ut1.scode = ut.scode
) mi

Return a Count of 0 When No Rows

OK, I've looked this up and tried a number of solutions, but can't get it to work. I'm a bit of a novice. Here's my original query - how can I get it to return 0 for an account when there are no results in the student table?
SELECT a.NAME
,count(s.student_sid)
FROM account a
JOIN inst i ON a.inst_sid = i.root_inst_sid
JOIN inst_year iy ON i.inst_sid = iy.inst_sid
JOIN student s ON iy.inst_year_sid = s.inst_year_sid
WHERE s.demo = 0
AND s.STATE = 1
AND i.STATE = 1
AND iy.year_sid = 16
AND a.account_sid IN (
20187987
,20188576
,20188755
,52317128
,20189249
)
GROUP BY a.NAME;
Use an outer join, moving the condition on that table into the join:
select a.name, count(s.student_sid)
from account a
join inst i on a.inst_sid = i.root_inst_sid
join inst_year iy on i.inst_sid = iy.inst_sid
left join student s on iy.inst_year_sid = s.inst_year_sid
and s.demo = 0
and s.state = 1
where i.state = 1
and iy.year_sid = 16
and a.account_sid in (20187987, 20188576, 20188755, 52317128, 20189249)
group by a.name;
count() does not count null values, which s.student_sid will be if no rows join from student.
You need to LEFT JOIN and then SUM() over the group where s.student_sid is not null:
select
a.name,
sum(case when s.student_sid is null then 0 else 1 end) as student_count
from account a
join inst i on a.inst_sid = i.root_inst_sid
join inst_year iy on i.inst_sid = iy.inst_sid
left join student s
on iy.inst_year_sid = s.inst_year_sid
and s.demo = 0
and s.state = 1
where i.state = 1
and iy.year_sid = 16
and a.account_sid in (20187987, 20188576, 20188755, 52317128, 20189249)
group by a.name;
This is assuming that all of the fields in the student table that you are filtering on are optional. If you don't want to enforce removal of records where, say, s.state does not equal 1, then you need to move the s.state=1 predicate into the WHERE clauses.
If, for some reason, you are getting duplicate student IDs and students are being counted twice, then you can change the aggregate function to this:
count(distinct s.student_id) as student_count
...which is safe to do as count(distinct ...) ignores null values.

SQL statement merge two rows into one

In the results of my sql-statement (SQL Server 2016) I would like to combine two rows with the same value in two columns ("study_id" and "study_start") into one row and keep the row with higest value in a third cell ("Id"). If any columns (i.e. "App_id" or "Date_arrival) in the row with higest Id is NULL, then it should take the value from the row with the lowest "Id".
I get the result below:
Id study_id study_start Code Expl Desc Startmonth App_id Date_arrival Efter_op Date_begin
167262 878899 954 4.1 udd.ord Afbrudt feb 86666 21-06-2012 N 17-08-2012
180537 878899 954 1 Afsluttet Afsluttet feb NULL NULL NULL NULL
And I would like to get this result:
Id study_id study_start Code Expl Desc Startmonth App_id Date_arrival Efter_op Date_begin
180537 878899 954 1 Afsluttet Afsluttet feb 86666 21-06-2012 N 17-08-2012
My statement looks like this:
SELECT dbo.PopulationStam_V.ELEV_ID AS id,
dbo.PopulationStam_V.PERS_ID AS study_id,
dbo.STUDIESTARTER.STUDST_ID AS study_start,
dbo.Optagelse_Studiestatus.AFGANGSARSAG AS Code,
dbo.Optagelse_Studiestatus.KORT_BETEGNELSE AS Expl,
ISNULL((CAST(dbo.Optagelse_Studiestatus.Studiestatus AS varchar(20))), 'Indskrevet') AS 'Desc',
dbo.STUDIESTARTER.OPTAG_START_MANED AS Startmonth,
dbo.ANSOGNINGER.ANSOG_ID as App_id,
dbo.ANSOGNINGER.ANKOMSTDATO AS Data_arrival',
dbo.ANSOGNINGER.EFTEROPTAG AS Efter_op,
dbo.ANSOGNINGER.STATUSDATO AS Date_begin
FROM dbo.INSTITUTIONER
INNER JOIN dbo.PopulationStam_V
ON dbo.INSTITUTIONER.INST_ID = dbo.PopulationStam_V.SEMI_ID
LEFT JOIN dbo.ANSOGNINGER
ON dbo.PopulationStam_V.ELEV_ID = dbo.ANSOGNINGER.ELEV_ID
INNER JOIN dbo.STUDIESTARTER
ON dbo.PopulationStam_V.STUDST_ID_OPRINDELIG = dbo.STUDIESTARTER.STUDST_ID
INNER JOIN dbo.UDD_NAVNE_T
ON dbo.PopulationStam_V.UDDA_ID = dbo.UDD_NAVNE_T.UDD_ID
INNER JOIN dbo.UDDANNELSER
ON dbo.UDD_NAVNE_T.UDD_ID = dbo.UDDANNELSER.UDDA_ID
LEFT OUTER JOIN dbo.PERSONER
ON dbo.PopulationStam_V.PERS_ID = dbo.PERSONER.PERS_ID
LEFT OUTER JOIN dbo.POSTNR
ON dbo.PERSONER.PONR_ID = dbo.POSTNR.PONR_ID
LEFT OUTER JOIN dbo.KønAlleElevID_V
ON dbo.PopulationStam_V.ELEV_ID = dbo.KønAlleElevID_V.ELEV_ID
LEFT OUTER JOIN dbo.Optagelse_Studiestatus
ON dbo.PopulationStam_V.AFAR_ID = dbo.Optagelse_Studiestatus.AFAR_ID
LEFT OUTER JOIN dbo.frafaldsmodel_adgangsgrundlag
ON dbo.frafaldsmodel_adgangsgrundlag.ELEV_ID = dbo.PopulationStam_V.ELEV_ID
LEFT OUTER JOIN dbo.Optagelse_prioriteterUFM
ON dbo.Optagelse_prioriteterUFM.cpr = dbo.PopulationStam_V.CPR_NR
AND dbo.Optagelse_prioriteterUFM.Aar = dbo.frafaldsmodel_adgangsgrundlag.optagelsesaar
LEFT OUTER JOIN dbo.frafaldsmodel_stoettetabel_uddannelser AS fsu
ON fsu.id_uddannelse = dbo.UDDANNELSER.UDDA_ID
AND fsu.id_inst = dbo.INSTITUTIONER.INST_ID
AND fsu.uddannelse_aar = dbo.frafaldsmodel_adgangsgrundlag.optagelsesaar
WHERE dbo.STUDIESTARTER.STUDIESTARTSDATO > '2012-03-01 00:00:00.000'
AND (dbo.Optagelse_Studiestatus.AFGANGSARSAG IS NULL
OR dbo.Optagelse_Studiestatus.AFGANGSARSAG NOT LIKE '2.7.4')
AND (dbo.PopulationStam_V.INDSKRIVNINGSFORM = '1100'
OR dbo.PopulationStam_V.INDSKRIVNINGSFORM = '1700')
GROUP BY dbo.PopulationStam_V.ELEV_ID,
dbo.PopulationStam_V.PERS_ID,
dbo.STUDIESTARTER.STUDST_ID,
dbo.Optagelse_Studiestatus.AFGANGSARSAG,
dbo.Optagelse_Studiestatus.KORT_BETEGNELSE,
dbo.STUDIESTARTER.OPTAG_START_MANED,
Studiestatus,
dbo.ANSOGNINGER.ANSOG_ID,
dbo.ANSOGNINGER.ANKOMSTDATO,
dbo.ANSOGNINGER.EFTEROPTAG,
dbo.ANSOGNINGER.STATUSDATO
I really hope somebody out there can help.
Many ways, this will work:
WITH subSource AS (
/* Your query here */
)
SELECT
s1.id,
/* all other columns work like this:
COALESCE(S1.column,s2.column)
for example: */
coalesce(s1.appid,s2.appid) as appid
FROM subSource s1
INNER JOIN subSource s2
ON s1.study_id =s2.study_id
and s1.study_start = s2.study_start
AND s1.id > s2.id
/* I imagine some other clauses might be needed but maybe not */
The rest is copy paste