alternative to sub query in join - sql-server

I have a SQL query that I'm trying to optimize.
Is there a better way to avoid using subquery here?
Got a suggestion on using Row_number(),
posting this with some corrections
DECLARE #curdate DATETIME
SET #curdate = GETDATE()
SELECT DISTINCT
SIS.StudentID, StudentCoverage.StudentCoverageDataID,
Student.FirstName, Student.LastName,
Student.DateOfBirth, Student.Gender,
ASMT.AssessmentDate
FROM
SIS (NOLOCK)
INNER JOIN
SISMaster (NOLOCK) ON SISMaster.SISID = SIS.SISID
INNER JOIN
Assessment ASMT ON SIS.StudentID = ASMT.StudentId
INNER JOIN
StudentCoverage (NOLOCK) ON StudentCoverage.StudentID = SIS.StudentID
INNER JOIN
Organization (NOLOCK) ON StudentCoverage.OrgID = Organization.OrganizationID
INNER JOIN
Student (NOLOCK) ON Student.StudentID = SIS.StudentID
INNER JOIN
StudentCoverageData (NOLOCK) ON StudentCoverageData.StudentCoverageID = StudentCoverage.StudentCoverageID
AND StudentCoverageData.StudentCoverageDataID = (SELECT TOP 1 StudentCoverageData.StudentCoverageDataID
FROM StudentCoverage
INNER JOIN StudentCoverageData ON StudentCoverageData.StudentCoverageID = StudentCoverage.StudentCoverageID
WHERE StudentCoverage.StudentId = SIS.StudentID
AND StudentCoverageData.Active = 1
AND StudentCoverageData.EffectiveDate <= #curdate
AND (StudentCoverageData.ExitDate IS NULL OR StudentCoverageData.ExitDate > #curdate)
ORDER BY StudentCoverageData.AsOfDate DESC)

All Tables in your subquery is exists in inner join clause, so you could rewrite your query like this:
;WITH temps AS
(
DECLARE #curdate DATETIME = GETDATE()
SELECT
SIS.StudentID, StudentCoverage.StudentCoverageDataID,
Student.FirstName, Student.LastName,
Student.DateOfBirth, Student.Gender,
ASMT.AssessmentDate,
ROW_NUMBER() OVER (PARTITION BY StudentCoverageData.StudentCoverageDataID ORDER BY StudentCoverageData.AsOfDate) AS RowIndex
FROM
SIS (NOLOCK)
INNER JOIN
SISMaster (NOLOCK) ON SISMaster.SISID = SIS.SISID
INNER JOIN
StudentCoverage (NOLOCK) ON StudentCoverage.StudentID = SIS.StudentID
INNER JOIN
Organization (NOLOCK) ON StudentCoverage.OrgID = Organization.OrganizationID
INNER JOIN
Student (NOLOCK) ON Student.StudentID = SIS.StudentID
INNER JOIN
StudentCoverageData (NOLOCK) ON StudentCoverageData.StudentCoverageID = StudentCoverage.StudentCoverageID
WHERE StudentCoverageData.Active = 1
AND StudentCoverageData.EffectiveDate <= #curdate
AND (StudentCoverageData.ExitDate IS NULL OR StudentCoverageData.ExitDate > #curdate)
)
SELECT * FROM temps t
WHERE t.RowIndex = 1

Related

SQL Server 2005 Select Data From Table1 and Table2 but if Table2 column1 value is null Select Data From Table3

My Query IS
SELECT TblPharmacyBillingDetails.UPBNo, TblMasterBillingData.IPDNo, InPatRegistration.PatTitle+PatientName, TblPharmacyBillingDetails.InvoiceNo, TblPharmacyBillingDetails.InvoiceDateTime, TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN InPatRegistration ON TblMasterBillingData.IPDNo = InPatRegistration.IPDNo
but if TblMasterBillingData.IPDNo value is NULL select Data From TblMasterBillingData.OPDNo and
INNER JOIN OutPatRegistration ON TblMasterBillingData.OPDNo = OutPatRegistration.IPDNo
Method #1: Using UNION
SELECT * FROm
(
SELECT TblPharmacyBillingDetails.UPBNo,
TblMasterBillingData.IPDNo,
InPatRegistration.PatTitle+PatientName,
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN InPatRegistration ON TblMasterBillingData.IPDNo = InPatRegistration.IPDNo
WHERE TblMasterBillingData.IPDNo IS NOT NULL
UNION ALL
SELECT TblPharmacyBillingDetails.UPBNo,
TblMasterBillingData.OPDNo,
OutPatRegistration .PatTitle + PatientName,
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
INNER JOIN OutPatRegistration ON TblMasterBillingData.OPDNo = OutPatRegistration.OPDNo
WHERE TblMasterBillingData.OPDNo IS NOT NULL
)Tmp
ORDER BY TblPharmacyBillingDetails.UPBNo
Method #2 Using ISNULL and LEFT JOIN
SELECT TblPharmacyBillingDetails.UPBNo,
ISNULL(TblMasterBillingData.IPDNo,TblMasterBillingData.OPDNo),
ISNULL(IP.PatTitle + IP.PatientName, OP.PatTitle + OP.PatientName),
TblPharmacyBillingDetails.InvoiceNo,
TblPharmacyBillingDetails.InvoiceDateTime,
TblPharmacyBillingDetails.BillingAmount
FROM TblPharmacyBillingDetails
INNER JOIN TblMasterBillingData ON TblPharmacyBillingDetails.UPBNo = TblMasterBillingData.UPBNo
LEFT JOIN InPatRegistration IP ON TblMasterBillingData.IPDNo = IP.IPDNo
LEFT JOIN outPatRegistration OP ON TblMasterBillingData.OPDNo = OP.OPDNo
ORDER BY TblPharmacyBillingDetails.UPBNo
You can write either case statement or ISNULL() function as shown below in the demo query.
SELECT
Orders.OrderID,
Case when Customers1.CustomerName is null then Customers2.CustomerName else Customers1.CustomerName
end as CustomerName, --way 1
ISNULL(Customers1.CustomerName, Customers2.CustomerName) as Customer, --way 2
Orders.OrderDate
FROM Orders
INNER JOIN Customers1 ON Orders.CustomerID = Customers1.CustomerID
INNER JOIN Customers2 ON Orders.CustomerID = Customers2.CustomerID
-- where your condition here
-- order by your column name
You can also check whether data is available or not in the table and join the table accordingly using if exists as shown below.
if exists(select 1 from tablename where columnname = <your values>)

SQL Server Select Not Returning All Rows

I have run into a very strange problem where a query is returning most rows but not all of them. If I add an addition condition to my where clause, the missing row appears.
Below is my query:
SELECT T1.Table1ID,
SUM(ISNULL([T4].Qty,0)) TotalQty
FROM dbo.Table1 (NOLOCK) T1
INNER JOIN [dbo].Table2 (NOLOCK) T2 ON T1.Table2ID = T2.Table2ID
INNER JOIN [dbo].Table3 (NOLOCK) T3 ON T2.DocTypeID = T3.DocTypeID
INNER JOIN dbo.Table4 (NOLOCK) T4 ON T4.Table1ID = T1.Table1ID
WHERE T3.is1 = 0
GROUP BY T1.Table1ID
ORDER BY T1.Table1ID
This returns all rows except for the one with T1.Table1ID = 185671. If I add it as a filter like such:
SELECT T1.Table1ID,
SUM(ISNULL([T4].Qty,0)) TotalQty
FROM dbo.Table1 (NOLOCK) T1
INNER JOIN [dbo].Table2 (NOLOCK) T2 ON T1.Table2ID = T2.Table2ID
INNER JOIN [dbo].Table3 (NOLOCK) T3 ON T2.DocTypeID = T3.DocTypeID
INNER JOIN dbo.Table4 (NOLOCK) T4 ON T4.Table1ID = T1.Table1ID
WHERE T3.is1 = 0
AND T1.Table1ID = 185671
GROUP BY T1.Table1ID
ORDER BY T1.Table1ID
Now the row shows. Any ideas?
EDIT: New query after removing NOLOCK hint.
SELECT T1.Table1ID,
SUM(ISNULL([T4].Qty,0)) TotalQty
FROM dbo.Table1 T1
INNER JOIN [dbo].Table2 T2 ON T1.Table2ID = T2.Table2ID
INNER JOIN [dbo].Table3 T3 ON T2.DocTypeID = T3.DocTypeID
INNER JOIN dbo.Table4 T4 ON T4.Table1ID = T1.Table1ID
WHERE T3.is1 = 0
AND T1.Table1ID = 185671
GROUP BY T1.Table1ID
ORDER BY T1.Table1ID

Duplicate records with Multiple joins

I had written a join query statement. that statement returns me multiple(duplicate) row again even though I'm having only single record on that.
declare #BenefitClass int ;
set #BenefitClass = (select BenefitClass From HJOB where userid='d76c5000-69e0-461e-92e1-3cfe7590d098' and CompanyId =1629)
select #BenefitClass;
select
bve.EmployerContribution,
bhsac.CatchUpValue as CatchUpValue ,
bcl.Tier,
bcl.planYear,
bhsac.Ischecked,
isnull(bhsac.Value,0) as EmployeeContribute,
Id=(convert(varchar, bcl.Id) + '$' + convert(varchar, isnull(bhsac.Id, 0))) ,
bhsac.Value ,
bhsac.HSALmitId
from
dbo.benContributionStructure bcs
inner join dbo.benVariableElection bve on bcs.PlanInfoId = bve.PlanInfoId
inner join dbo.benBenefitContributionLimit bcl on bcs.SavingCategory = bcl.CategoryID
left outer join dbo.benBenefitHSACoverage bhsac on bcs.PlanInfoId = bhsac.planInfoId
and bcl.Id=bhsac.HSALmitId --and bhsac.BenefitClassId=#BenefitClass
and bhsac.UserID='d76c5000-69e0-461e-92e1-3cfe7590d098' and bhsac.PlanInfoId=38044
left outer join dbo.benEmployeeContribution bec on bhsac.UserID = bec.UserId and bhsac.BenefitClassId = bec.BenefitClassId -- and bec.EnrollmentType !='Closed'
left outer join benOpenEnrollment oems on oems.ID = bec.OpenEnrollmentId and oems.EndDt > GETDATE()
where
bcs.PlanInfoId=38044 and bcl.Ischecked=1
and bcl.Tier !='CatchUp'
and bcl.CompanyId=1629
For that I'm getting the result as second row as duplicate :
observe the result
Try this once it may help you
declare #BenefitClass int ;
set #BenefitClass = (select BenefitClass From HJOB where userid='d76c5000-69e0-461e-92e1-3cfe7590d098' and CompanyId =1629)
select #BenefitClass;
;with cte as (
select
bve.EmployerContribution,
bhsac.CatchUpValue as CatchUpValue ,
bcl.Tier,
bcl.planYear,
bhsac.Ischecked,
isnull(bhsac.Value,0) as EmployeeContribute,
Id=(convert(varchar, bcl.Id) + '$' + convert(varchar, isnull(bhsac.Id, 0))) ,
bhsac.Value ,
bhsac.HSALmitId
from
dbo.benContributionStructure bcs
inner join dbo.benVariableElection bve on bcs.PlanInfoId = bve.PlanInfoId
inner join dbo.benBenefitContributionLimit bcl on bcs.SavingCategory = bcl.CategoryID
left outer join dbo.benBenefitHSACoverage bhsac on bcs.PlanInfoId = bhsac.planInfoId
and bcl.Id=bhsac.HSALmitId --and bhsac.BenefitClassId=#BenefitClass
and bhsac.UserID='d76c5000-69e0-461e-92e1-3cfe7590d098' and bhsac.PlanInfoId=38044
left outer join dbo.benEmployeeContribution bec on bhsac.UserID = bec.UserId and bhsac.BenefitClassId = bec.BenefitClassId -- and bec.EnrollmentType !='Closed'
left outer join benOpenEnrollment oems on oems.ID = bec.OpenEnrollmentId and oems.EndDt > GETDATE()
where
bcs.PlanInfoId=38044 and bcl.Ischecked=1
and bcl.Tier !='CatchUp'
and bcl.CompanyId=1629
)
select distinct EmployerContribution,
CatchUpValue ,Tier,planYear,Ischecked,EmployeeContribute,Id ,Value ,HSALmitId from cte
Please change your where condition as below:
select
bve.EmployerContribution,
bhsac.CatchUpValue as CatchUpValue ,
bcl.Tier,
bcl.planYear,
bhsac.Ischecked,
isnull(bhsac.Value,0) as EmployeeContribute,
Id=(convert(varchar, bcl.Id) + '$' + convert(varchar, isnull(bhsac.Id, 0))) ,
bhsac.Value ,
bhsac.HSALmitId
from
dbo.benContributionStructure bcs
inner join dbo.benVariableElection bve on bcs.PlanInfoId = bve.PlanInfoId
inner join dbo.benBenefitContributionLimit bcl on bcs.SavingCategory = bcl.CategoryID
left outer join dbo.benBenefitHSACoverage bhsac on bcs.PlanInfoId = bhsac.planInfoId
and bcl.Id=bhsac.HSALmitId --and bhsac.BenefitClassId=#BenefitClass
left outer join dbo.benEmployeeContribution bec on bhsac.UserID = bec.UserId and bhsac.BenefitClassId = bec.BenefitClassId -- and bec.EnrollmentType !='Closed'
left outer join benOpenEnrollment oems on oems.ID = bec.OpenEnrollmentId
where
bcs.PlanInfoId=38044 and bcl.Ischecked=1
and bcl.Tier !='CatchUp'
and bcl.CompanyId=1629
and bhsac.UserID='d76c5000-69e0-461e-92e1-3cfe7590d098'
and bhsac.PlanInfoId=38044
and oems.EndDt > GETDATE()

How to return latest record from SQL Server

I have this query:
SELECT
t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,
t_ticket.code, t_ticket.priority, t_orgSection.title,
t_actionTicket.addedDateAction, t_actionTicket.title AS Expr1
FROM
t_actionTicket
INNER JOIN
t_ticket ON t_actionTicket.ticketID_FK = t_ticket.ticketID
INNER JOIN
t_orgSection ON t_ticket.orgSectionID_FK = t_orgSection.orgSectionID
WHERE
(t_ticket.userID_FK = #userid) AND (t_ticket.cusDelete = 0)
I want to return just the latest record in t_actionTicket table for each row in t_ticket table.
You can use row_number to pick just the top row for each ticket ID, by ordering by your date and then making row = 1 one of your join criteria. See as follows:
Replace
FROM t_actionTicket INNER JOIN
t_ticket ON t_actionTicket.ticketID_FK = t_ticket.ticketID
with
FROM
(select *
, row_number() over (partition by ticketID_FK order by TicketActionDate desc) as RN
from t_actionTicket ) at
INNER JOIN t_ticket
ON at.ticketID_FK = t_ticket.ticketID and at.RN = 1
I guessed at the name of your date column in ActionTicket, so you will probably need to change that.
You can try this one too, just alternative:
SELECT t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,t_ticket.code, t_ticket.priority, t_orgSection.title,t_actionTicket.addedDateAction, t_actionTicket.title AS Expr1
FROM t_ticket INNER JOIN
(select TOP 1 t_actionTicket.* from t_actionTicket INNER JOIN
t_ticket on t_ticket.ticketID = t_actionTicket.ticketID_FK ORDER BY
t_actionTicket.addedDateAction DESC ) AS t_actionTicket
ON t_actionTicket.ticketID_FK = t_ticket.ticketID
INNER JOIN t_orgSection ON t_ticket.orgSectionID_FK = t_orgSection.orgSectionID
WHERE (t_ticket.userID_FK = #userid) AND (t_ticket.cusDelete = 0)
I assume that addedDateAction uses timestamp when new record is inserted.
I find this solution
SELECT t_ticket.ticketID, t_ticket.addedDate, t_ticket.question,
t_ticket.code, t_ticket.priority, t_actionTicket.addedDateAction,
t_actionTicket.title AS Expr1
FROM t_actionTicket INNER JOIN t_ticket ON
t_actionTicket.ticketID_FK = t_ticket.ticketID INNER JOIN
(SELECT ticketID_FK, MAX(addedDateAction) AS maxDate
FROM t_actionTicket AS t_actionTicket_1
GROUP BY ticketID_FK) AS b ON t_actionTicket.ticketID_FK = b.ticketID_FK AND t_actionTicket.addedDateAction = b.maxDate
WHERE (t_ticket.userID_FK = #userid) AND (t_ticket.cusDelete = 0)

Get Max(id) from one to many table

I know this question was asked many times but I was tring and trying without success
I have one to many relationship between two tables and some more inner-joins to get more data.
Here is my query:
SELECT
ShopOffer.OfferID,
ShopOffer.OfferMessage,
Shop.ID,
Shop.Name,
Shop.Phone,
[User].Name,
[User].UserID,
ShopOfferStatus.Name AS StatusName,
BlockedShopInUser.IsBlocked
FROM
ShopOffer
INNER JOIN ShopOfferStatus ON ShopOffer.ShopOfferStatusID = ShopOfferStatus.ShopOfferStatusID
INNER JOIN Shop ON ShopOffer.ShopID = Shop.ShopID
INNER JOIN UserRequest ON ShopOffer.UserRequestID = UserRequest.UserRequestID
INNER JOIN [User] ON UserRequest.UserID = [User].UserID
INNER JOIN BlockedShopInUser ON Shop.ShopID = BlockedShopInUser.ShopID AND [User].UserID = BlockedShopInUser.UserID
Each shop can create many offers. In that query I would like to get only the last offer for each shop.
Thanks.
Here is a way:
;WITH LastShopOffer AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY ShopID ORDER BY OfferID DESC)
FROM ShopOffer
)
SELECT
SO.OfferID,
SO.OfferMessage,
S.ID,
S.Name,
S.Phone,
U.Name,
U.UserID,
SOS.Name AS StatusName,
B.IsBlocked
FROM ( SELECT *
FROM LastShopOffer
WHERE RN = 1) SO
INNER JOIN ShopOfferStatus SOS
ON SO.ShopOfferStatusID = SOS.ShopOfferStatusID
INNER JOIN Shop S
ON SO.ShopID = S.ShopID
INNER JOIN UserRequest UR
ON SO.UserRequestID = UR.UserRequestID
INNER JOIN [User] U
ON UR.UserID = U.UserID
INNER JOIN BlockedShopInUser B
ON S.ShopID = B.ShopID
AND U.UserID = B.UserID;
I think you have to start with Shop and then perform a CROSS APPLY on the TOP 1 record from ShopOffer:
SELECT
ShopOffer.OfferID,
ShopOffer.OfferMessage,
Shop.ID,
Shop.Name,
Shop.Phone,
[User].Name,
[User].UserID,
ShopOfferStatus.Name AS StatusName,
BlockedShopInUser.IsBlocked
FROM Shop
CROSS APPLY (
SELECT TOP 1 OfferID, OfferMessage, ShopOfferStatusID, UserRequestID
FROM ShopOffer AS s
WHERE s.ShopID = Shop.ShopID
ORDER BY s.OfferID DESC
) ShopOffer
INNER JOIN ShopOfferStatus ON ShopOffer.ShopOfferStatusID = ShopOfferStatus.ShopOfferStatusID
INNER JOIN UserRequest ON ShopOffer.UserRequestID = UserRequest.UserRequestID
INNER JOIN [User] ON UserRequest.UserID = [User].UserID
INNER JOIN BlockedShopInUser ON Shop.ShopID = BlockedShopInUser.ShopID AND [User].UserID = BlockedShopInUser.UserID

Resources