How can I select a column from a NOT-IN sub-query - sql

Here is a query that I need help with:
SELECT s.lastfirst, s.student_number, s.grade_level
FROM students s
WHERE s.schoolid = 300 AND s.enroll_status = 0 AND s.id not in
(
SELECT d.studentid
FROM section_meeting em INNER JOIN sections e
ON em.sectionid = e.id
INNER JOIN cc d ON e.id = d.sectionid
WHERE em.schoolid = 300 and em.period_number in (P1)
)
This query works fine except that I need to show the column em.period_number in the results as well. Can anyone suggest how to go about it?
Thanks!

query works fine exept that I need to show the column em.period_number
in the results as well
If you have successfully got the result using your question query let me add period_number with join query..try :
SELECT s.lastfirst, s.student_number, s.grade_level, section_meeting.period_number
FROM students s INNER JOIN
section_meeting ON s.schoolid = section_meeting.schoolid
WHERE (s.schoolid = 300) AND (s.enroll_status = 0) AND (s.id NOT IN
(SELECT d.studentid
FROM section_meeting em INNER JOIN
sections e ON em.sectionid = e.id INNER JOIN
cc d ON e.id = d.sectionid
WHERE (em.schoolid = 300) AND (em.period_number IN (P1))))

Related

Left Outer Join returning results to be excluded

I have a query like
WITH a AS ( SELECT *
FROM inventory_tagalongs
WHERE TagAlong_ItemNum <> 'bokiwi2'
)
SELECT inventory.itemnum
, inventory.itemname
, inventory.ItemType,inventory.dept_id
FROM inventory
LEFT OUTER JOIN a
ON inventory.itemnum = a.itemnum
JOIN departments
ON inventory.dept_id = departments.dept_id
JOIN categories
ON departments.subtype = categories.cat_id AND categories.description = 'vapors'
in which i am trying to exclude a's results from the lower syntax but the results return are exactly the same whether or not left outer join..... is there or not.
Do i have my syntax incorrect here?
Good afternoon. Please try this:
select
inventory.itemnum
, inventory.itemname
, inventory.ItemType
, inventory.dept_id
from inventory
join departments on inventory.dept_id=departments.dept_id
join categories on departments.subtype=categories.cat_id and categories.description='vapors'
WHERE NOT EXISTS(
select 1 from inventory_tagalongs B where inventory.itemnum = b.itemnum
AND B.TagAlong_ItemNum <>'bokiwi2');
The CTE overthought the issue a bit. This accomplishes the goal with easier-to-read code and should perform better as well.
Thanks, John.
If you are trying to get results that don't have the tag, your logic is inverted. You want:
SELECT i.itemnum, i.itemname, i.ItemType, i.dept_id
FROM inventory i JOIN
departments d
ON i.dept_id = d.dept_id JOIN
categories c
ON d.subtype = c.cat_id AND
c.description = 'vapors' LEFT OUTER JOIN
a
ON i.itemnum = a.itemnum
WHERE a.itemnum IS NULL;
You don't need a CTE for this at all. It would usually be written as:
WITH a AS (
)
SELECT i.itemnum, i.itemname, i.ItemType, i.dept_id
FROM inventory i JOIN
departments d
ON i.dept_id = d.dept_id JOIN
categories c
ON d.subtype = c.cat_id AND
c.description = 'vapors' LEFT OUTER JOIN
inventory_tagalongs it
ON i.itemnum = it.itemnum AND it.TagAlong_ItemNum = 'bokiwi2'
WHERE a.itemnum IS NULL;
And -- as mentioned in another answer -- NOT EXISTS is another typical way to approach this problem.

Trying to find Mentor/mentee pairs that have not submitted a certain report

Trying to find the mentor-mentee groups that have not submitted a specific report (reported = 147). All the pairs have submitted reports but I need the ones who have specifically not submitted 147 yet.
Thanks
SELECT DISTINCT
e2.Firstname Mentor_FN
,e2.lastname Mentor_LN
,e1.Firstname Mentee_FN
,e1.lastname Mentee_LN
,r.ReportID
FROM
MentorRelationshipStaging m
INNER JOIN Employee e1
ON e1.EmployeeCode = m.MenteeCode
INNER JOIN Employee e2
ON e2.EmployeeCode = m.MentorCode
INNER JOIN UserReport ur1
ON ur1.EmployeeID = e2.EmployeeID
INNER JOIN Report r
ON r.reportID = ur1.ReportID
DATABASE:https://imgur.com/a/9JMRpFw
I would suggest:
SELECT e2.Firstname Mentor_FN, e2.lastname Mentor_LN, e1.Firstname Mentee_FN, e1.lastname Mentee_LN
FROM MentorRelationshipStaging m INNER JOIN
Employee e1
ON e1.EmployeeCode = m.MenteeCode INNER JOIN
Employee e2
ON e2.EmployeeCode = m.MentorCode LEFT JOIN
UserReport ur1
ON ur.EmployeeID = e2.EmployeeID
GROUP BY e2.Firstname Mentor_FN, e2.lastname Mentor_LN, e1.Firstname Mentee_FN, e1.lastname Mentee_LN
HAVING SUM(CASE WHEN ur.ReportId = 147 THEN 1 ELSE 0 END) = 0 ;
Or, if you don't want to use GROUP BY:
SELECT e2.Firstname Mentor_FN, e2.lastname Mentor_LN, e1.Firstname Mentee_FN, e1.lastname Mentee_LN
FROM MentorRelationshipStaging m INNER JOIN
Employee e1
ON e1.EmployeeCode = m.MenteeCode INNER JOIN
Employee e2
ON e2.EmployeeCode = m.MentorCode LEFT JOIN
UserReport ur1
ON ur.EmployeeID = e2.EmployeeID AND ur.ReportId = 147
WHERE ur.EmployeeId IS NULL;
Notes:
The key is the LEFT JOIN to be sure you get people who have submitted no reports.
The Reports table is not needed, because the ReportId is in UserReport.
I am a bit suspicious about the JOIN to UserReport. You are suggesting that the "mentor" is always submitting the report.
SELECT DISTINCT
e2.Firstname Mentor_FN
,e2.lastname Mentor_LN
,e1.Firstname Mentee_FN
,e1.lastname Mentee_LN
,r.ReportID
FROM
MentorRelationshipStaging m
INNER JOIN Employee e1
ON e1.EmployeeCode = m.MenteeCode
INNER JOIN Employee e2
ON e2.EmployeeCode = m.MentorCode
INNER JOIN UserReport ur1
ON ur1.EmployeeID = e2.EmployeeID
INNER JOIN Report r
ON r.reportID = ur1.ReportID and ur1.ReportID=147
I can't be more specific because don't know your schema. But this is usually solve with GROUP BY and HAVING using a conditional COUNT
GROUP BY e2.Firstname
,e2.lastname
,e1.Firstname
,e1.lastname
HAVING COUNT(CASE WHEN reported = 147 THEN 1 END) = 0

How to retrieve count of records in SELECT statement

I am trying to retrieve the right count of records to mitigate an issue I am having. The below query returns 327 records from my database:
SELECT DISTINCT COUNT(at.someid) AS CountOfStudentsInTable FROM tblJobSkillAssessment AS at
INNER JOIN tblJobSkills j ON j.jobskillid = at.skillid
LEFT JOIN tblStudentPersonal sp ON sp.someid2 = at.someid
INNER JOIN tblStudentSchool ss ON ss.monsterid = at.someid
INNER JOIN tblSchools s ON s.schoolid = ss.schoolid
INNER JOIN tblSchoolDistricts sd ON sd.schoolid = s.schoolid
INNER JOIN tblDistricts d ON d.districtid = sd.districtid
INNER JOIN tblCountySchools cs ON cs.schoolid = s.schoolid
INNER JOIN tblCounties cty ON cty.countyid = cs.countyid
INNER JOIN tblRegionUserRegionGroups rurg ON rurg.districtid = d.districtid
INNER JOIN tblGroups g ON g.groupid = rurg.groupid
WHERE ss.graduationyear IN (SELECT Items FROM FN_Split(#gradyears, ',')) AND sp.optin = 'Yes' AND g.groupname = #groupname
Where I run into trouble is trying to reconcile that with the below query. One is for showing just a count of all the particular students the other is showing pertinent information for a set of students as needed but the total needs to be the same and it is not. The below query return 333 students - the reason is because the school the student goes to is in two separate counties and it counts that student twice. I can't figure out how to fix this.
SELECT DISTINCT #TableName AS TableName, d.district AS LocationName, cty.county AS County, COUNT(DISTINCT cc.monsterid) AS CountOfStudents, d.IRN AS IRN FROM tblJobSkillAssessment AS cc
INNER JOIN tblJobSkills AS c ON c.jobskillid = cc.skillid
INNER JOIN tblStudentPersonal sp ON sp.monsterid = cc.monsterid
INNER JOIN tblStudentSchool ss ON ss.monsterid = cc.monsterid
INNER JOIN tblSchools s ON s.schoolid = ss.schoolid
INNER JOIN tblSchoolDistricts sd ON sd.schoolid = s.schoolid
INNER JOIN tblDistricts d ON d.districtid = sd.districtid
INNER JOIN tblCountySchools cs ON cs.schoolid = s.schoolid
INNER JOIN tblCounties cty ON cty.countyid = cs.countyid
INNER JOIN tblRegionUserRegionGroups rurg ON rurg.districtid = d.districtid
INNER JOIN tblGroups g ON g.groupid = rurg.groupid
WHERE ss.graduationyear IN (SELECT Items FROM FN_Split(#gradyears, ',')) AND sp.optin = 'Yes' AND g.groupname = #groupname
GROUP BY cty.county, d.IRN, d.district
ORDER BY LocationName ASC
If you just want the count, then perhaps count(distinct) will solve the problem:
select count(distinct at.someid)
I don't see what at.someid refers to, so perhaps:
select count(distinct cc.monsterid)

Using a sum with a distinct in SQL

I have a query that returns the data i'm looking for using a distinct, but when I SUM that data I get a wrong amount for a my hierachy point '4-2-0-0-5-2'. 4-2-0-0-5-2 has multiple rows so when I sum it, it doesn't add up correctly. What would be the best way to incorporate a distinct into a SUM statement. Any help would be appreicated. Thanks.
First query :
Select distinct B.Proj_Nbr,c.proj_cc,h.proj_cc, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per, A.Amount
from acct_bal a
inner join dim_proj b on a.dim_proj_id = b.dim_proj_id
inner join essbase_fcs.projects_hier_map c on c.proj_nbr = b.proj_nbr
inner join dim_per_mo d on d.dim_per_mo_id = a.dim_per_mo_id
Inner Join Dim_Acct F On A.Dim_Acct_Id = F.Dim_Acct_Id
Inner Join Dim_Org G On A.Dim_Org_Id = G.Dim_Org_Id
inner join essbase_fcs.projects_hier_map h on h.proj_cc = g.cost_ctr
inner join dim_org g1 on c.proj_cc = g1.cost_ctr
Where F.Fin_Lee_Nbr = 500
and c.proj_hier like '4-2-0-0-5-2%'
And A.Dim_Scnro_Id = '45'
And D.Fscl_Yr = '2014'
And b.Proj_Nbr = '9005459'
and fscl_per ='1'
RESULT of 2 rows:
9005459 0358080 0358080 4-2-0-0-5-2 Global Sales.com (iSell) 179777.09
9005459 0358080 0358057 4-2-0-0-5-5 Global Sales.com (iSell) 2257.3**
When I want to sum the data I use this query below. This gives me the two rows i'm looking for, but proj_hier 4-2-0-0-5-2 has the wrong amount because it has multiple rows.
Select B.Proj_Nbr,c.proj_cc, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per, sum(A.Amount)
from acct_bal a
inner join dim_proj b on a.dim_proj_id = b.dim_proj_id
inner join essbase_fcs.projects_hier_map c on c.proj_nbr = b.proj_nbr
inner join dim_per_mo d on d.dim_per_mo_id = a.dim_per_mo_id
Inner Join Dim_Acct F On A.Dim_Acct_Id = F.Dim_Acct_Id
Inner Join Dim_Org G On A.Dim_Org_Id = G.Dim_Org_Id
inner join essbase_fcs.projects_hier_map h on h.proj_cc = g.cost_ctr
inner join dim_org g1 on c.proj_cc = g1.cost_ctr
Where F.Fin_Lee_Nbr = 500
and c.proj_hier like '4-2-0-0-5-2%'
And A.Dim_Scnro_Id = '45'
And D.Fscl_Yr = '2014'
And b.Proj_Nbr = '9005459'
and fscl_per ='1'
group by B.Proj_Nbr,c.proj_cc,f.dim_acct_id, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per
having Sum(A.Amount) <> 0
Order By H.Proj_Hier, B.Proj_Nbr, D.Fscl_Per
Please Generalize the Question and then ask, If i understood your problem Here is solution:
General Query :
select sum(a.amountColumn) from your_table
group by agrrColumnName;
If i change your query :
Select distinct B.Proj_Nbr,c.proj_cc,h.proj_cc, h.Proj_Hier, B.Proj_Nm, D.Fscl_Per, sum(A.Amount)
from acct_bal a
inner join dim_proj b on a.dim_proj_id = b.dim_proj_id
inner join essbase_fcs.projects_hier_map c on c.proj_nbr = b.proj_nbr
inner join dim_per_mo d on d.dim_per_mo_id = a.dim_per_mo_id
Inner Join Dim_Acct F On A.Dim_Acct_Id = F.Dim_Acct_Id
Inner Join Dim_Org G On A.Dim_Org_Id = G.Dim_Org_Id
inner join essbase_fcs.projects_hier_map h on h.proj_cc = g.cost_ctr
inner join dim_org g1 on c.proj_cc = g1.cost_ctr
Where F.Fin_Lee_Nbr = 500
and c.proj_hier like '4-2-0-0-5-2%'
And A.Dim_Scnro_Id = '45'
And D.Fscl_Yr = '2014'
And b.Proj_Nbr = '9005459'
and fscl_per ='1' group by B.Proj_Nbr;

Add a filter parameter to ssrs report

I have a query that I need to update to allow user to filter out pending applications. I have created the parameter and tried to implement using case but it is not working or giving any error messages on how to correct it. The code is:
select distinct pers.person_fname,
pers.person_mname,
pers.person_lname,
le.nationalprovidernumber NPN,
lic.licensenumber LICENSE_NUMBER,
adr.address_line1 ADDRESS1,
adr.address_line2 ADDRESS2,
adr.address_line3 ADDRESS3,
adr.city CITY,
sp.state_province_name STATE,
adr.postal_code ZIP_CODE,
eml.email,
rtp.residencetype_name RESIDENCY,
ltp.licensetype_name LICENSE_TYPE,
lic.expirationdate DATE_OF_EXPIRATION
from odilic_admin.license lic
inner join odilic_admin.licenseststimeline lst
on lic.license_id = lst.license_id
inner join odilic_admin.licenseststype lstp
on lst.licenseststype_id = lstp.licenseststype_id
inner join odilic_admin.licensedef ldef
on lic.licensedef_id = ldef.licensedef_id
inner join odilic_admin.licensetype ltp
on ldef.licensetype_id = ltp.licensetype_id
inner join odilic_admin.residencetype rtp
on ldef.residencetype_id = rtp.residencetype_id
inner join odilic_admin.licensingentity le
on lic.licensingentity_id = le.licensingentity_id
inner join odilic_admin.individual ind
on le.licensingentity_id = ind.licensingentity_id
inner join odidir_admin.person pers
on ind.person_id = pers.person_id
left outer join odidir_admin.person_address_rel par
on pers.person_id = par.person_id
left outer join odidir_admin.address adr
on par.address_id = adr.address_id
left outer join odidir_admin.address_type atp
on adr.address_type_id = atp.address_type_id
left outer join odidir_admin.state_province sp
on adr.state_province_id = sp.state_province_id
left outer join
(select pr.person_id, em.email_id, em.email
from odidir_admin.person pr,
odidir_admin.person_email_rel pe,
odidir_admin.email em
where pr.person_id = pe.person_id
and pe.email_id = em.email_id
and email_type_id = 2) eml
on pers.person_id = eml.person_id
where
ltp.licensetype_id in (:License_type)
and lstp.licenseststype_name = 'Active'
and atp.address_type_name = 'Mailing Licensing'
and (lic.expirationdate >= current_date and
trunc(lic.expirationdate) = :Expiration_Date)
and sysdate between lst.periodbegindate and lst.periodenddate
order by lic.licensenumber
In order to get applications that are pending I need to access the table odilic_admin.licenseappl and filter out all licenses with appststype = 2 (pending). To do this I added a join to the query before the last left outer join andt hen a case at bottom for when this parameter is selected.
select distinct pers.person_fname,
pers.person_mname,
pers.person_lname,
le.nationalprovidernumber NPN,
lic.licensenumber LICENSE_NUMBER,
adr.address_line1 ADDRESS1,
adr.address_line2 ADDRESS2,
adr.address_line3 ADDRESS3,
adr.city CITY,
sp.state_province_name STATE,
adr.postal_code ZIP_CODE,
eml.email,
rtp.residencetype_name RESIDENCY,
ltp.licensetype_name LICENSE_TYPE,
lic.expirationdate DATE_OF_EXPIRATION
from odilic_admin.license lic
inner join odilic_admin.licenseststimeline lst
on lic.license_id = lst.license_id
inner join odilic_admin.licenseststype lstp
on lst.licenseststype_id = lstp.licenseststype_id
inner join odilic_admin.licensedef ldef
on lic.licensedef_id = ldef.licensedef_id
inner join odilic_admin.licensetype ltp
on ldef.licensetype_id = ltp.licensetype_id
inner join odilic_admin.residencetype rtp
on ldef.residencetype_id = rtp.residencetype_id
inner join odilic_admin.licensingentity le
on lic.licensingentity_id = le.licensingentity_id
inner join odilic_admin.individual ind
on le.licensingentity_id = ind.licensingentity_id
inner join odidir_admin.person pers
on ind.person_id = pers.person_id
left outer join odidir_admin.person_address_rel par
on pers.person_id = par.person_id
left outer join odidir_admin.address adr
on par.address_id = adr.address_id
left outer join odidir_admin.address_type atp
on adr.address_type_id = atp.address_type_id
left outer join odidir_admin.state_province sp
on adr.state_province_id = sp.state_province_id
**left outer join odilic_admin.licenseappl appl
on lic.licensingentity_id = appl.licenseappl_id**
left outer join
(select pr.person_id, em.email_id, em.email
from odidir_admin.person pr,
odidir_admin.person_email_rel pe,
odidir_admin.email em
where pr.person_id = pe.person_id
and pe.email_id = em.email_id
and email_type_id = 2) eml
on pers.person_id = eml.person_id
where
ltp.licensetype_id in (:License_type)
and lstp.licenseststype_name = 'Active'
and atp.address_type_name = 'Mailing Licensing'
and (lic.expirationdate >= current_date and
trunc(lic.expirationdate) = :Expiration_Date)
and sysdate between lst.periodbegindate and lst.periodenddate
**case :pending when = yes then appl.applststype_id !=2
end**
order by lic.licensenumber
Instead of the case I have also tried using an IF with the same result. This looks like:
if :Pending = 1
then
and appl.applststype_id != 2;
end if;
Any help to get me past this is greatly appreciated and I will be sure to vote and select most correct answer to help me solve this.
Assuming that your :pending parameter is a numeric where a value of 1 indicates that pending licences are to be excluded and you only want to exclude licence applications that are pending, try adding the following condition in place of your existing case clause:
and (:pending <> 1 or appl.applststype_id !=2)