Null/0 Answers Not Appearing - sql

Another Question for Today :)
Wrote a query that works perfectly - except I want it to show NULL/0 values as 0 - and - that isn't happening. I tried approaching this two ways:
First I used isnull()
Select isnull(Count(*),0) as Total ,
z.zname
From STable s ,
SLTable sl ,
ZTable z ,
SETable se ,
SEETable see ,
SEGTable seg
Where s.sID = sl.sID
and sl.zID = z.zID
and s.sID = se.sID
and se.etID = see.etID
and see.segID = seg.segID
and see.segID = 3
Group By z.zname
order by z.zname
Is doesn't seem to give me the Null/0 values
Then I tried using a sum/case approach
Select sum(case when see.segID <> 3 then 0 else 1 end) as Total ,
z.zname
From STable s ,
SLTable sl ,
Table z ,
SETable se ,
SEETable see ,
SEGTable seg
Where s.sID = sl.sID
and sl.zID = z.zID
and s.sID = se.sID
and se.etID = see.etID
and see.segID = seg.segID
and see.segID = 3
Group By z.zname
order by z.zname
And still no 0 values - so now I'm stumped :(

Well, it's unclear what you're actually trying to find. However, a big part of your problem is that you're using old-school, pre-ISO/ANSI join syntax. If you refactor your join to use modern join syntax, you'll get a query that looks somethinn (a lot, actually) like this:
select zName = z.zname ,
Total = count(*)
From ZTable z
join SLTable sl on sl.zID = z.zID
join STable s on s.sID = sl.sID
join SETable se on se.sID = s.sID
join SEETable see on see.etID = se.etID
and see.segID = 3
join SEGTable seg on seg.segID = see.segID
Group By z.zname
order by z.zname
I suspect that what you want to get is a list of all zNames and their respect counts of having segID = 3. Since you are using inner joins, you'll only ever see zNames that have a match. What you can do is something like this:
select zName = z.zname ,
Total = sum(case see.segID when 3 then 1 else 0 end)
from ZTable z
left join SLTable sl on sl.zID = z.zID
left join STable s on s.sID = sl.sID
left join SETable se on se.sID = s.sID
left join SEETable see on see.etID = se.etID
group By z.zname
order by z.zname
The above will return every row from zTable at least once, with null values for the columns of any table for which no match was found. Then we group it and count the rows where segID is 3.

Actually just to semi answer my own question - just realized that where - see.segID-3 - so it'll only turn out results with segID = 3 - so it cannot NOT have 3 - right?
But Im specifically looking for segIDs as 3 - just, if there is nothing there then display 0

Here's what I am assuming you need changed
Select
Count(*) as Total,
z.zname
From STable s, SLTable sl, ZTable z, SETable se, SEETable see, SEGTable seg
Where s.sID=sl.sID
and sl.zID=z.zID
and s.sID=se.sID
and se.etID=see.etID
and see.segID=seg.segID
and see.segID=3
AND TABLE.YOURCOLUMN IS NOT NULL -- THESE ARE
AND TABLE.YOURCOLUMN <> 0 -- NEW
GROUP BY z.zname
ORDER BY z.zname

In your Query
isnull(Count(*),0) as Total,
Count will never return null, it will be numeric values ranging from 0 to n.
So your isnull condition will never get satisfy.
You can simply write select count() as total .. instead of isnull(Count(),0) and it will return 0 when ever it will find no rows in table.

Related

SQL Count condition in main Query

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).

SQL Server : Pivot Table Odd result,

So, full disclosure, this is my first time using a pivot table and the result set has multiple columns as a result. In this example, we will use the result set without a pivot table applied.
This student has taken multiple courses. What the ideal end result would be, is to count how many courses this student has taken. So if I look I see that the Student has taken Algebra 1 5 times, English 1 2 times and Geometry 2 times.
The Next image is the query with the pivot applied, oh and to make things complicated, its a monster query before trying to attempt the pivot.
So we see in this, that Algebra 1 has a count of 0, Geometry has a count of 2 and English has a count of 0. This is the same query as before but just using this student.
Query:
SELECT *
FROM
(SELECT
[StudentNumber], psat.MathScaledScore, psat.EBRWScore,
SCReady.MathScaleScore, SCReady.ReadingScaleScore,
SpringMap.MathPercentile, SpringMap.ReadingPercentile,
Coursework.Course_name
FROM
[OnlineApplications].[dbo].[Users] U
LEFT JOIN
[OnlineApplications].[dbo].ContactInfoes C ON C.ContactInfoId = U.UserId
LEFT JOIN
(SELECT *
FROM [DOENRICH-SQL].[enrich_prod].dbo.HCS_view_Most_Recent_PSAT_Scores Scores) AS psat ON U.StudentNumber = psat.number
LEFT JOIN
(SELECT
stud.Number, sc.DateTaken,
CASE sc.ELALev
WHEN 'E8AE0E4D-AD36-41D8-AC89-627D19661803' THEN 'Exceeds Expectations'
WHEN 'C9F2CDA2-D904-438B-9DD3-94EFC9111A0E' THEN 'Approaches Expectations'
WHEN '9B39E28F-89C8-44AD-A8F2-1463192F88F1' THEN 'Does Not Meet Expectation'
WHEN '87247DB1-4A57-419E-9619-7B43B02B1135' THEN 'Meets Expectations'
END ELALev,
sc.ELASS AS ELAScaleScore, sc.elavss AS VerticalScaleScore,
sc.elassread AS ReadingScaleScore,
sc.ELARS10 AS RawScoreStandard10, sc.elASPR AS ELAStatePercentileRank,
MathLev = CASE MathLev
WHEN 'E8AE0E4D-AD36-41D8-AC89-627D19661803' THEN 'Exceeds Expectations'
WHEN 'C9F2CDA2-D904-438B-9DD3-94EFC9111A0E' THEN 'Approaches Expectations'
WHEN '9B39E28F-89C8-44AD-A8F2-1463192F88F1' THEN 'Does Not Meet Expectation'
WHEN '87247DB1-4A57-419E-9619-7B43B02B1135' THEN 'Meets Expectations'
END,
sc.MATHSS AS MathScaleScore, sc.MathVSS AS MathVerticalScaleScore,
sc.mathspr AS MathStatePercentileRank
FROM
[DOENRICH-SQL].[enrich_prod].dbo.t_sc_ready sc
JOIN
[DOENRICH-SQL].[enrich_prod].dbo.Student stud ON sc.StudentID = stud.ID
WHERE
DateTaken = '2019-05-17') AS SCReady ON SCReady.number = U.studentnumber
LEFT JOIN
(
select stud.Number, max(map.readingPercentile) as ReadingPercentile, max(map.mathPercentile) as MathPercentile
from [DOENRICH-SQL].[ENRICH_PROD].[dbo].t_map map
join [DOENRICH-SQL].[ENRICH_PROD].[INFORM].[Map_GradeLevelID] mapping on map.GradeLevelID = mapping.DestID
JOIN [DOENRICH-SQL].[ENRICH_PROD].[dbo].[Student] stud on map.StudentID = stud.ID
where DateTaken >= '2018-08-01'
group by stud.Number
) as SpringMap on SpringMap.number = U.Studentnumber
left join (
SELECT * FROM OPENQUERY(PSPROD,'
Select B.STUDENT_NUMBER , A.COURSE_NAME, A.GRADE_LEVEL, A.SCHOOLNAME, A.GRADE
from PS.STOREDGRADES A
join PS.STUDENTS B ON A.STUDENTID = B.ID
AND STORECODE in (''Q1'',''Q2'',''Q3'',''Q4'',''F1'')
AND (COURSE_NAME LIKE ''%Algebra 1%'' OR COURSE_NAME LIKE ''%Geometry Honors%'' OR COURSE_NAME LIKE ''%English 1%'')
group by B.STUDENT_NUMBER , A.COURSE_NAME, a.STORECODE, A.GRADE, A.PERCENT, A.GRADE_LEVEL, A.SCHOOLNAME
ORDER BY STUDENT_NUMBER, STORECODE DESC
'
)
) as Coursework on Coursework.STUDENT_NUMBER = U.StudentNumber
join [OnlineApplications].[dbo].ScholarsApps Sapps on Sapps.ScholarsAppId = u.UserId
where AppYear = 2019 and StudentNumber <> '' and StudentNumber = '17476'
) T
PIVOT (
COUNT (COURSE_NAME)
FOR course_name IN (
[Algebra 1],
[Geometry Honors],
[English 1])
)
as Pivot_table
Again, very complicated query before and I'm not clear if I'm using the pivot function correctly.
I'd love to have this pivot with the counts of the courses.

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

PIVOT on multiple columns SQL server (Aspen Relay Database)

I'm using a vendor supplied Relay Database (Aspen), which is running on MS SQL server). I'm attempting to write a pivot query that needs to pivot on 2 columns.
I created a temp table since the data is across multiple tables.
WITH TEMP_TABLE AS (
SELECT
R.LOCATIONID LLOCATIONID, R.ID RID, s.groupname SGROUPNAME,t.settingname TSETTINGNAME, s.setting SSETTING
from tsetting1 s
inner join tsettype1 t on t.relaytype=s.relaytype and t.groupname = s.groupname and t.rownumber = s.rownumber
INNER JOIN TREQUEST Q ON S.REQUESTID = Q.ID
INNER JOIN TRELAY R ON R.ID = Q.RELAYID
INNER JOIN TLOCATION L ON L.ID = R.LOCATIONID
where s.requestid=29117
)
select * from TEMP_TABLE
That select all from Temp returns 38 rows of data, a subset is shown here:
RID -----SGROUPNAME------TSETTINGNAME-------SSETTING
31297 LOAD1 ENABLE TRUE
31297 LOAD1 ANGLE 60
31297 LOAD2 CALCULATED_LOAD 12269
ETC....
I added this pivot, which gets me close:
PIVOT (MAX(SSETTING) FOR TSETTINGNAME IN (ENABLE, REACH, ANGLE, CALCULATED_LOADABILITY, ZLE, CTR, PTR, KVNOM, PICKUP, PERCENTAGE)) P
Returned result from Pivot:
RID-----SGROUPNAME-----ENABLE----REACH----ANGLE----CALCULATED_LOADABILITY
31297 LOAD1 TRUE 15 60 9444
31297 LOAD2 TRUE 10 30 12269
31297 LOAD3 TRUE 20 60 14167
ETC...
I would like to have the data as 1 record for RID 31297, where LOAD1-ENABLE, LOAD2-ENABLE, LOAD3-ENABLE, LOAD1-REACH, ETC. are all headers.
I've tried multiple pivots and cross apply, but I can't seem to get the data to display correctly.
Let me know if anything is unclear or if you need more information. Any help will be greatly appreciated.
Thanks,
Joe C.
It may be easier with a bunch of case statements and a group by RID. By the way this is the "original" method of pivoting before PIVOT was implemented.
select RID
, Load1_Enable = MAX(case when SGROUPNAME = 'Load1' then enable else null end)
, Load2_Enable = MAX(case when SGROUPNAME = 'Load2' then enable else null end)
from [YourTable]
group by RID
I would go all the way to the first cte though:
WITH TEMP_TABLE AS (
SELECT
R.LOCATIONID LLOCATIONID, R.ID RID, s.groupname SGROUPNAME,t.settingname TSETTINGNAME, s.setting SSETTING
from tsetting1 s
inner join tsettype1 t on t.relaytype=s.relaytype and t.groupname = s.groupname and t.rownumber = s.rownumber
INNER JOIN TREQUEST Q ON S.REQUESTID = Q.ID
INNER JOIN TRELAY R ON R.ID = Q.RELAYID
INNER JOIN TLOCATION L ON L.ID = R.LOCATIONID
where s.requestid=29117
)
select RID
,Load1_Enable = MAX(case when SGROUPNAME = 'Load1' and TSETTINGNAME = 'Enable' then SSETTING else null end)
from TEMP_TABLE
group by RID
Note MAX is only there for an aggregate -- you should be aggregating only one record.

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.