How to select top when already selected fields - sql

Just wanted to ask how to add a 'select top 1 *' when I've already selected fields from a list? I seen examples in other codes but don't quite get it. Thought will be easier if see it in a code I constructed.
Below is an example of a query I have:
select frp.ProductPersonID,frp.FlightSeatId, frp.PlusMealId, per.TitleID, per.surname, per.FirstName, per.PersonTypeId, tor.PersonID, tor.Reference
from package pk
inner join product p on p.packageid = pk.packageid
inner join productperson pp on pp.productid = p.productid
inner join person per on per.personid = pp.personid
left join flightlogicalseat fls on fls.productpersonid = pp.productpersonid
inner join TourOperatorReference tor on tor.PersonID = per.PersonId
inner join FlightReservationPassenger frp on frp.ProductPersonID = pp.ProductPersonId
where pk.Reference LIKE '%'
and ProductTypeId =1

Simply try to use TOP keyword like this:
select TOP 1 frp.ProductPersonID,frp.FlightSeatId, frp.PlusMealId, per.TitleID,

You can just wrap your existing query in new query:
SELECT TOP 1 * FROM
(select frp.ProductPersonID,frp.FlightSeatId, frp.PlusMealId, per.TitleID, per.surname, per.FirstName, per.PersonTypeId, tor.PersonID, tor.Reference
from package pk
inner join product p on p.packageid = pk.packageid
inner join productperson pp on pp.productid = p.productid
inner join person per on per.personid = pp.personid
left join flightlogicalseat fls on fls.productpersonid = pp.productpersonid
inner join TourOperatorReference tor on tor.PersonID = per.PersonId
inner join FlightReservationPassenger frp on frp.ProductPersonID = pp.ProductPersonId
where pk.Reference LIKE '%'
and ProductTypeId =1) t

Related

Trouble with aggregate in Where clause, Selecting Max(x) When Max(x) != 3

I am trying to reconfigure the below sql to only pull records when the Max(Field) != 3 but keep getting an error (detailed) below.
This is the code before adding the Where Max(field) != 3
SELECT P.Code,
MAX(PW.v1) AS V1
FROM SW
INNER JOIN S ON SW.S_Id = S.Id
INNER JOIN PW ON SW.PW_Id = PW.Id
INNER JOIN PON S.P_Id = P.id
WHERE S.P_Id = P.id
GROUP BY P.Code
My Attempt
SELECT P.Code,
MAX(PW.v1) AS V1
FROM SW
INNER JOIN S ON SW.S_Id = S.Id
INNER JOIN PW ON SW.PW_Id = PW.Id
INNER JOIN PON S.P_Id = P.id
WHERE S.P_Id = P.id
AND (SELECT MAX(PW.v1)
FROM SW AS SW2
WHERE SW.PWId = SW2.PW_Id) != 3
GROUP BY P.Code
This is the error I get and not sure what to do:
An aggregate may not appear in the WHERE clause unless it is in a subquery contained in a HAVING clause or a select list, and the column being aggregated is an outer reference.
Traditional method of filtering on results of an aggregate can be achieved by using HAVING clause. I also removed the unnecessary WHERE clause as you already joined those 2 tables on that column. Here is the query:
SELECT P.Code
,MAX(PW.v1) AS V1
FROM SW
INNER JOIN S
ON SW.S_Id = S.Id
INNER JOIN PW
ON SW.PW_Id = PW.Id
INNER JOIN P
ON S.P_Id = P.id
GROUP BY P.Code
HAVING MAX(PW.v1)!=3;

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.

How to omit the table join based on some condition?

=======================
SELECT *
FROM PRODUCT P
JOIN PRODUCT_LOC PL
ON P.PRODUCT_ID = PL.PRODUCT_ID
JOIN PRODUCT_LOC_DEF PLD AND PL.LOC_ID = PLD.LOC_ID
JOIN PRODUCT_CURRENT_LOC PCL
ON PLD.LOC_ID = PCL.LOC_ID AND P.PRODUCT_ID = PCL.PRODUCT_ID
How should I modify the query to get expected result in case 1 and case 2 as given in attached snapshot?
Preferred:
I am looking for the modification in the same query instead of making two query and union them.
Just use a left join instead of an inner join:
SELECT *
FROM PRODUCT P
LEFT JOIN PRODUCT_LOC PL ON P.PRODUCT_ID = PL.PRODUCT_ID
LEFT JOIN PRODUCT_LOC_DEF PLD AND PL.PRODUCT_LOC_ID = PLD.LOC_ID
LEFT JOIN PRODUCT_CURRENT_LOC PCL ON PLD.LOC_ID = PCL.LOC_ID
You should try this:
SELECT * FROM
PRODUCT p
INNER JOIN
PRODUCT_CURRENT_LOC pcl
ON
p.PRODUCT_ID = pcl.PRODUCT_ID
INNER JOIN
PRODUCT_LOC pc
ON
pc.LOC_ID = pcl.LOC_ID
UNION
SELECT * FROM
PRODUCT p
LEFT OUTER JOIN
PRODUCT_CURRENT_LOC pcl
ON
p.PRODUCT_ID = pcl.PRODUCT_ID
AND
pcl.PRODUCT_ID IS NULL
LEFT OUTER JOIN
PRODUCT_LOC pc
ON
pc.LOC_ID = pcl.LOC_ID
AND
pc.LOC_ID IS NULL

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)

sql query sum bringing back different results

I have the following two queries below, the Total is coming back different, but I am adding the sums in each of the query the same way. Why is the total coming back different?
select [Total Children] = (SUM(demo.NumberOfPreschoolers) + SUM(demo.NumberOfToddlers) + SUM(demo.NumberOfInfants)),
County = co.Description
from ClassroomDemographics as demo
inner join Classrooms as c on demo.Classroom_Id = c.Id
inner join Sites as s on c.Site_Id = s.Id
inner join Profiles as p on s.Profile_Id = p.Id
inner join Dictionary.Counties as co on p.County_Id = co.Id
where co.Description = 'MyCounty'
Group By co.Description
select [Number Of DLL Children] = SUM(cd.NumberOfLanguageSpeakers),
[Total Children] = (SUM(demo.NumberOfPreschoolers) + SUM(demo.NumberOfToddlers) + SUM(demo.NumberOfInfants)),
County = co.Description
from ClassroomDLL as cd
inner join Classrooms as c on cd.Classroom_Id = c.Id
inner join Sites as s on c.Site_Id = s.Id
inner join Profiles as p on s.Profile_Id = p.Id
inner join Dictionary.Counties as co on p.County_Id = co.Id
inner join ClassroomDemographics as demo on c.Id = demo.Classroom_Id
where co.Description = 'MyCounty'
Group by co.Description
Just a quick glance over the two querties, I would presume that:
inner join ClassroomDemographics as demo on c.Id = demo.Classroom_Id
in the second query is excluding results that are in the first query, therefor the aggregated values will be different.
Your join to the Classrooms table is joining with an extra table in the 2nd query.
Query 1:
from ClassroomDemographics as demo
inner join Classrooms as c on demo.Classroom_Id = c.Id
Query 2:
from ClassroomDLL as cd
inner join Classrooms as c on cd.Classroom_Id = c.Id
...
inner join ClassroomDemographics as demo on c.Id = demo.Classroom_Id
My bet is that the ClassroomDLL table has less data in it, or has rows with a null for one of the join criteria columns, either of which could exclude rows from the results and throw your aggregate totals off.