I am writing a stored procedure to retrieve purchases out of Microsoft Great Plains so they can be processed.
Great Plains has two invoice table sets of note. SOP10100/SOP10200 contain the invoice header and details of an invoice that has not yet been posted. SOP30200/SOP30300 contain the invoice header and details of invoices that have been posted. When a product is purchased, it immediately goes into SOP10100/SOP10200, and once it is posted, it is moved from SOP10100/SOP10200 to SOP30200/SOP30300. There is a common table SOP10106 that contains user-defined fields and can be joined to either table set.
When pulling purchases, we need to check both tables in case an invoice gets posted before it can be processed. Up until now, the only way we've been able to achieve this is through a UNION, which is basically two identical queries with the difference being that one joins to SOP10100/SOP10200 and the other joins to SOP30200/SOP30300.
I'm hoping to find a way that we can pare this down into a single query (utilizing the shared SOP10106 table) to hopefully get one result set that only contains the records that have either a SOP10100/SOP10200 or SOP30200/SOP30300 record. The join to the GP tables is within the OPENQUERY function.
The SPROC is below:
SELECT [Account1].AccountID, [Account1].AccountNumber AS 'Order_OrgID', [Account2].AccountNumber AS 'CI_OrgID', [Contact].cncy_CustomerNumber AS 'CustomerID', [Contact].EMailAddress1 AS 'Email', [Contact].FirstName, [Contact].LastName, [StringMapMarket].Value AS 'Market',
GP.Invoice, GP.SKU, MAP.Name, GP.OrderDate, GP.Quantity, GP.SLPRSNID, RTRIM(GP.SKU) + '-' + [StringMapMarket].Value COLLATE DATABASE_DEFAULT as AdjSku, MAP.CourseID, MAP.SubscriptionID
FROM OPENQUERY(GPSERVER, 'SELECT [SOP10100].SOPNUMBE AS Invoice, [SOP10200].ITEMNMBR AS SKU, [SOP10200].ITEMDESC AS Product, [SOP10100].CREATDDT AS OrderDate, [SOP10200].QTYORDER AS Quantity,
[SOP10100].SLPRSNID, [SOP10100].CUSTNMBR, [SOP10106].USERDEF1, [SOP10100].SOPTYPE, [SOP10100].VOIDSTTS
FROM CPI.dbo.SOP10100 WITH (NOLOCK)
INNER JOIN CPI.dbo.SOP10200 WITH (NOLOCK) ON [SOP10100].SOPNUMBE = [SOP10200].SOPNUMBE AND [SOP10100].CREATDDT > DATEADD(ww,-4,GETDATE())
INNER JOIN CPI.dbo.SOP10106 WITH (NOLOCK) ON [SOP10100].SOPNUMBE = [SOP10106].SOPNUMBE WHERE [SOP10200].SOPTYPE = 3
AND [SOP10100].VOIDSTTS <> 1
AND NOT [SOP10106].USERDEF1 = ''INTERNAL LMS''') as GP
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account1] WITH(NOLOCK) ON GP.CUSTNMBR = [Account1].AccountNumber COLLATE DATABASE_DEFAULT
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Contact WITH(NOLOCK) ON GP.USERDEF1 = [Contact].cncy_customernumber COLLATE DATABASE_DEFAULT
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account2] WITH(NOLOCK) ON [Contact].ParentCustomerId = [Account2].Id
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapMarket] WITH(NOLOCK) ON [Account1].cncy_MarketType = [StringMapMarket].AttributeValue AND [StringMapMarket].AttributeName = 'cncy_MarketType' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapCountry] WITH(NOLOCK) ON [Contact].cncy_address1country = [StringMapCountry].AttributeValue AND [StringMapCountry].AttributeName = 'cncy_address1country' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.vwLmsMapping AS MAP WITH(NOLOCK) ON MAP.Subscription = 'true' AND
CASE
WHEN [StringMapCountry].Value IN ('US','Canada') THEN RTRIM(GP.SKU) + '-' +
CASE
WHEN [StringMapMarket].Value IN ('HE','MH') THEN 'HE'
WHEN [StringMapMarket].Value IN ('ED') THEN 'ED'
ELSE 'HS'
END
ELSE RTRIM(GP.SKU)
END = map.SKU
LEFT OUTER JOIN SeatLog WITH(NOLOCK) ON GP.Invoice = [SeatLog].Invoice AND RTRIM(GP.SKU) = [SeatLog].SKU
WHERE GP.SOPTYPE = 3
AND GP.VOIDSTTS <> 1
AND NOT GP.USERDEF1 = 'INTERNAL LMS'
AND [SubscriptionLog].ID IS NULL
UNION
SELECT [Account1].AccountID, [Account1].AccountNumber AS 'Order_OrgID', [Account2].AccountNumber AS 'CI_OrgID', [Contact].cncy_CustomerNumber AS 'CustomerID', [Contact].EMailAddress1 AS 'Email', [Contact].FirstName, [Contact].LastName, [StringMapMarket].Value AS 'Market',
GP.Invoice, GP.SKU, MAP.Name, GP.OrderDate, GP.Quantity, GP.SLPRSNID, RTRIM(GP.SKU) + '-' + [StringMapMarket].Value COLLATE DATABASE_DEFAULT as AdjSku, MAP.CourseID, MAP.SubscriptionID
FROM OPENQUERY(GPSERVER, 'SELECT [SOP30200].SOPNUMBE AS Invoice, [SOP30300].ITEMNMBR AS SKU, [SOP30300].ITEMDESC AS Product, [SOP30200].CREATDDT AS OrderDate, [SOP30300].QTYORDER AS Quantity,
[SOP30200].SLPRSNID, [SOP30200].CUSTNMBR, [SOP10106].USERDEF1, [SOP30200].SOPTYPE, [SOP30200].VOIDSTTS
FROM CPI.dbo.SOP30200 WITH (NOLOCK)
INNER JOIN CPI.dbo.SOP30300 WITH (NOLOCK) ON [SOP30200].SOPNUMBE = [SOP30300].SOPNUMBE AND [SOP30200].CREATDDT > DATEADD(ww,-4,GETDATE())
INNER JOIN CPI.dbo.SOP10106 WITH (NOLOCK) ON [SOP30200].SOPNUMBE = [SOP10106].SOPNUMBE WHERE [SOP30300].SOPTYPE = 3
AND [SOP30200].VOIDSTTS <> 1
AND NOT [SOP10106].USERDEF1 = ''INTERNAL LMS''') as GP
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account1] WITH(NOLOCK) ON GP.CUSTNMBR = [Account1].AccountNumber COLLATE DATABASE_DEFAULT
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Contact WITH(NOLOCK) ON GP.USERDEF1 = [Contact].cncy_customernumber COLLATE DATABASE_DEFAULT
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account2] WITH(NOLOCK) ON [Contact].ParentCustomerId = [Account2].Id
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapMarket] WITH(NOLOCK) ON [Account1].cncy_MarketType = [StringMapMarket].AttributeValue AND [StringMapMarket].AttributeName = 'cncy_MarketType' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapCountry] WITH(NOLOCK) ON [Contact].cncy_address1country = [StringMapCountry].AttributeValue AND [StringMapCountry].AttributeName = 'cncy_address1country' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.vwLmsMapping AS MAP WITH(NOLOCK) ON MAP.Subscription = 'true' AND
CASE
WHEN [StringMapCountry].Value IN ('US','Canada') THEN RTRIM(GP.SKU) + '-' +
CASE
WHEN [StringMapMarket].Value IN ('HE','MH') THEN 'HE'
WHEN [StringMapMarket].Value IN ('ED') THEN 'ED'
ELSE 'HS'
END
ELSE RTRIM(GP.SKU)
END = map.SKU
LEFT OUTER JOIN SeatLog WITH(NOLOCK) ON GP.Invoice = [SeatLog].Invoice AND RTRIM(GP.SKU) = [SeatLog].SKU
WHERE GP.SOPTYPE = 3
AND GP.VOIDSTTS <> 1
AND NOT GP.USERDEF1 = 'INTERNAL LMS'
AND [SubscriptionLog].ID IS NULL
Does anyone know of any ideas to simplify this without having to use a UNION? I'm hoping to improve the performance.
I tried to do it a different way by using FULL JOIN and COALESCE as follows:
SELECT COALESCE(Table1.SOPNUMBE, Table2.SOPNUMBE) AS 'SOPNUMBE', COALESCE(Table1.ITEMNMBR, Table2.ITEMNMBR) AS 'SKU', COALESCE(Table1.CUSTNMBR, Table2.CUSTNMBR) AS 'Account_Number', [SubscriptionLog].ID
FROM (SELECT SOP10100.SOPNUMBE,SOP10200.ITEMNMBR,SOP10100.CUSTNMBR FROM [GPSERVER].CPI.dbo.SOP10100 INNER JOIN [GPSERVER].CPI.dbo.SOP10200 ON SOP10100.SOPNUMBE = SOP10200.SOPNUMBE) AS Table1
FULL JOIN (SELECT SOP30200.SOPNUMBE,SOP30300.ITEMNMBR,SOP30200.CUSTNMBR FROM [GPSERVER].CPI.dbo.SOP30200 INNER JOIN [GPSERVER].CPI.dbo.SOP30300 ON SOP30200.SOPNUMBE = SOP30300.SOPNUMBE) AS Table2 ON Table1.SOPNUMBE = Table2.SOPNUMBE AND Table1.ITEMNMBR = Table2.ITEMNMBR AND Table1.CUSTNMBR = Table2.CUSTNMBR
INNER JOIN [GPSERVER].CPI.dbo.SOP10106 WITH(NOLOCK) ON COALESCE(Table1.SOPNUMBE, Table2.SOPNUMBE) = SOP10106.SOPNUMBE
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account1] WITH(NOLOCK) ON COALESCE(Table1.CUSTNMBR, Table2.CUSTNMBR) = [Account1].AccountNumber COLLATE DATABASE_DEFAULT
INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Contact WITH(NOLOCK) ON SOP10106.USERDEF1 = [Contact].cncy_customernumber COLLATE DATABASE_DEFAULT
--INNER JOIN [CRMSERVER].CPI_MSCRM.dbo.Account AS [Account2] WITH(NOLOCK) ON [Contact].ParentCustomerId = [Account2].Id
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapMarket] WITH(NOLOCK) ON [Account1].cncy_MarketType = [StringMapMarket].AttributeValue AND [StringMapMarket].AttributeName = 'cncy_MarketType' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.StringMap AS [StringMapCountry] WITH(NOLOCK) ON [Contact].cncy_address1country = [StringMapCountry].AttributeValue AND [StringMapCountry].AttributeName = 'cncy_address1country' AND [StringMapMarket].ObjectTypeCode = 2
INNER JOIN CPIProcessData.dbo.vwLmsMapping AS MAP WITH(NOLOCK) ON MAP.Subscription = 'true' AND
CASE
WHEN [StringMapCountry].Value IN ('US','Canada') THEN RTRIM(COALESCE(Table1.ITEMNMBR, Table2.ITEMNMBR)) + '-' +
CASE
WHEN [StringMapMarket].Value IN ('HE','MH') THEN 'HE'
WHEN [StringMapMarket].Value IN ('ED') THEN 'ED'
ELSE 'HS'
END
ELSE RTRIM(COALESCE(Table1.ITEMNMBR, Table2.ITEMNMBR))
END = map.SKU
LEFT OUTER JOIN [SubscriptionLog] WITH(NOLOCK) ON SOP10106.SOPNUMBE = [SubscriptionLog].Invoice AND RTRIM(COALESCE(Table1.ITEMNMBR, Table2.ITEMNMBR)) = [SubscriptionLog].SKU
WHERE [SubscriptionLog].ID IS NULL
It seems to run a little better, but it returns duplicates and not the results I expect.
Related
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>)
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
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()
So my stored procedure has a staff column that should be generating a staff name from my Employee table. The staff name only shows up on for some of the rows. Can anyone take a look and see where my error is here:
BEGIN
IF EXISTS (SELECT 1 FROM [user] (NOLOCK)
WHERE [user].ID = #UserID
AND [user].BrandID IS NULL AND [user].SpaID IS NULL)
BEGIN
DECLARE #OrderStatusID_Completed int, #OrderStatusID_Shipped int
SET #OrderStatusID_Shipped = 4
SET #OrderStatusID_Completed = 2
SELECT
CAST('' AS varchar(50)) AS ErrMsg
, o.OrderNumber
, Customer.GUID AS CustomerGUID
, OrderItem_View.DateCreated AS ItemDate
, COALESCE(MasterProductVariant.SKU, ProductVariant.SKU, Treatment.SKU) AS SKU
, DynamicPrice.FinalPrice AS Price
--, COALESCE(MasterProductVariant.OriginalPrice, ProductVariant.OriginalPrice, Treatment.Price) AS Price
, ISNULL(Employee.FirstName,'') + ' ' + ISNULL(Employee.LastName,'') AS Staff
, COALESCE(Product.Name, Treatment.Name) AS Item
, NULL AS Note
FROM
[Order] o (Nolock)
LEFT JOIN
Customer (Nolock) ON o.CustomerID = Customer.ID
INNER JOIN
OrderItem_View (nolock) ON OrderItem_View.OrderID = o.ID
LEFT JOIN
DynamicPrice (nolock) ON OrderItem_View.DynamicPriceID = DynamicPrice.ID
LEFT JOIN
AppointmentTreatment WITH (NOLOCK) ON AppointmentTreatment.ID = OrderItem_View.AppointmentTreatmentID
LEFT JOIN
Employee (NOLOCK) ON Employee.ID = COALESCE(OrderItem_View.EmployeeID, OrderItem_View.Employee2ID, AppointmentTreatment.EmployeeID)
LEFT JOIN
Treatment_View Treatment (nolock) ON Treatment.BillableItemID = OrderItem_View.BillableItemID
LEFT JOIN
ProductVariant (NOLOCK)
LEFT JOIN
Product (NOLOCK) ON Product.ID = ProductVariant.ProductID
ON ProductVariant.BillableItemID = OrderItem_View.BillableItemID
LEFT JOIN
ProductVariant MasterProductVariant (NOLOCK) ON ProductVariant.MasterRecordID = MasterProductVariant.ID
WHERE
o.SpaID = #SpaID
AND o.IsDeleted = 0
AND o.DateCompleted >= CONVERT(DATETIME,0)
AND o.DateCompleted < GetDate()
AND o.StatusID IN (#OrderStatusID_Completed,#OrderStatusID_Shipped)
END
ELSE
SELECT CAST('Insufficient rights.' AS VARCHAR(50)) AS ErrMsg
END
It has to be in the coalesce function. Somewhere between these three - you aren't getting a value
OrderItem_View.EmployeeID
OrderItem_View.Employee2ID
AppointmentTreatment.EmployeeID
So run OrderItem_View by itself and see if there are instances where EmployeeID or Employee2ID is ever null. If so, then try to determine what employees are missing. IF there are employees missing, are they also missing in the AppointmentTreatment table? If so then therein lies the problem.
Well, lets start.
I have 4 servers with the same database. There is a query that works fine to get data from each DB individually. Its something like this:
SELECT "blablablablabla"
FROM [UNION_ALL_BASES]..OVPM T01 with (nolock)
INNER JOIN [UNION_ALL_BASES]..VPM2 T11 with (nolock) ON T01.UnionAll_Empresa = T11.UnionAll_Empresa and T01.DocEntry = T11.DocNum
INNER JOIN [UNION_ALL_BASES]..PCH6 T2 with (nolock) ON T11.UnionAll_Empresa = T2.UnionAll_Empresa and T11.DocEntry = T2.DocEntry and T11.InstId = T2.InstlmntID
INNER JOIN [UNION_ALL_BASES]..OPCH T3 with (nolock) ON T2.UnionAll_Empresa = T3.UnionAll_Empresa and T2.DocEntry = T3.DocEntry
INNER JOIN [UNION_ALL_BASES]..PCH1 T3a with (nolock) ON T3.UnionAll_Empresa = T3a.UnionAll_Empresa and T3.DocEntry = T3a.DocEntry
LEFT JOIN [UNION_ALL_BASES]..OOCR T3b with (nolock) ON T3a.UnionAll_Empresa = T3b.UnionAll_Empresa and T3a.OcrCode2 = T3b.OcrCode
INNER JOIN [UNION_ALL_BASES]..OSLP T4 with (nolock) ON T4.UnionAll_Empresa = T4.UnionAll_Empresa and T3.SlpCode = T4.SlpCode
and T11.InvType = ''18''
AND T01.Canceled <> ''Y''
AND T01.CashSum > 0
Today we have one new database that merges all these 4 DBs. Each table of this new DB is a view with and Union All, with the difference that now I added a new column named "UnionAll_Empresa", to know from what server this row came from.
For example:
CREATE VIEW AACP as
SELECT 'G8Networks Solucoes' as UnionAll_Empresa, * from SBO_G8NETWORKS_SOLUCOES.dbo.AACP
UNION All
SELECT 'G8Networks NIC' as UnionAll_Empresa, * from SBO_G8NETWORKS_NIC.dbo.AACP
UNION All
SELECT 'SPIN' as UnionAll_Empresa, * from SBO_SPIN.dbo.AACP
UNION All
SELECT 'FA2R' as UnionAll_Empresa, * from SBO_FA2R.dbo.AACP;
Now I need to use that old query again, with these new "tables". The problem is that now the primary keys are not unique anymore, since there are 4 servers in the same table. So the solution would be to add the "UnionAll_Empresa" field (wich tells the name of the server) as a key along with the primary keys in the query. The new query would be something like this:
SELECT "blalalalalala"
FROM [UNION_ALL_BASES]..OVPM T01 with (nolock)
INNER JOIN [UNION_ALL_BASES]..VPM2 T11 with (nolock) ON T01.DocEntry = T11.DocNum and T01.UnionAll_Empresa = T11.UnionAll_Empresa
INNER JOIN [UNION_ALL_BASES]..PCH6 T2 with (nolock) ON T11.DocEntry = T2.DocEntry and T11.InstId = T2.InstlmntID and T11.UnionAll_Empresa = T2.UnionAll_Empresa
INNER JOIN [UNION_ALL_BASES]..OPCH T3 with (nolock) ON T2.DocEntry = T3.DocEntry and T2.UnionAll_Empresa = T3.UnionAll_Empresa
INNER JOIN [UNION_ALL_BASES]..PCH1 T3a with (nolock) ON T3.DocEntry = T3a.DocEntry and T3.UnionAll_Empresa = T3a.UnionAll_Empresa
LEFT JOIN [UNION_ALL_BASES]..OOCR T3b with (nolock) ON T3a.OcrCode2 = T3b.OcrCode and T3a.UnionAll_Empresa = T3b.UnionAll_Empresa
INNER JOIN [UNION_ALL_BASES]..OSLP T4 with (nolock) ON T3.SlpCode = T4.SlpCode and T4.UnionAll_Empresa = T4.UnionAll_Empresa
WHERE T11.InvType = ''18''
AND T01.Canceled <> ''Y''
AND T01.CashSum > 0
But it shows an error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
It stills find multiple results for some primary key, even when I add the comparison with the column "UnionAll_Empresa" (the name of the original server).
Am I doing something wrong?
--- Here is the full query
set #vQuery = '
SELECT --Pagametos de NF em dinheiro
T01.UnionAll_Empresa,
Base = ''' + #database + ''',
NomeEmp = (select a.CompnyName from [UNION_ALL_BASES]..OADM a with (nolock)),
CNPJ = (select a.TaxIdNum from [UNION_ALL_BASES]..oadm a with (nolock)),
IE = (Select TaxIdNum2 from [UNION_ALL_BASES]..OADM with (nolock)),
Filial = (Select PrintHeadr from [UNION_ALL_BASES]..OADM with (nolock)),
Proj = isnull(T3.Project,''''),
OcrCode2 = isnull(T3a.OcrCode2,''0''),
OcrName = isnull(T3b.OcrName,''Sem projeto definido''),
''NF'' TipoDoc,
''DIN'' Tipo,
T01.CardCode,
T01.CardName,
CardFName = (select CardFName from [UNION_ALL_BASES]..OCRD with (nolock) where OCRD.CardCode = T01.CardCode and OCRD.UnionAll_Empresa = T01.UnionAll_Empresa),
T01.DocEntry CodigoBaixaPagamento,
T11.DocEntry NumeroSapDocumento,
T01.DocDate DataDocBaixa,
T3.DocDate,
T11.InstId Parcela,
'''' SituacaoParc,
''1900-01-01'' DataUltBaixa,
T11.InvType,
T2.InsTotal ValorDaParcelaOriginal,
T01.DocDate DataLancamentoBaixa,
T2.DueDate VencimentoOriginalParcela,
T3.SeqCode,
SerieNF = (select SeqName from [UNION_ALL_BASES]..NFN1 with (nolock) where SeqCode = T3.SeqCode and UnionAll_Empresa = T3.UnionAll_Empresa),
T3.Series,
T3.Serial,
T3.SlpCode,
T4.SlpName,
round((T3a.LineTotal/T3.DocTotal)*(T11.SumApplied/T01.DocTotal)*(T01.CashSum),2) ValorPago,
T01.DocTotal TotalBaixa,
T01.CashSum TotalDinBaixa,
T01.TrsfrSum TotalTransfBaixa,
T01.[CheckSum] TotalCHBaixa,
T01.BoeSum TotalBoeBaixa,
T01.CreditSum TotalCCredBaixa,
Case
When T01.CashSum > 0 Then ''Dinheiro''
When T01.TrsFrSum > 0 Then ''TransferĂȘncia''
When T01.CreditSum > 0 Then ''Cartao''
End TipoDocumento,
'''' NossoNumBol,
'''' DigNossoNumBol,
''1900-01-01'' VencBoleto,
'''' CodBancoBol,
'''' NomeBancoBol,
0 VlrTotBol,
'''' NomeFPagtoBol,
'''' LinhaDigBol,
'''' TrsfrRef,
'''' NumCH,
'''' DataCH,
'''' StatusCH,
0 VlrTotCH,
'''' BancoCH,
'''' AgenciaCH,
'''' ContaCH,
'''' BoeStatus,
'''' CodCCred,
'''' NomeCCred,
'''' NumComprCartao,
0 NumParcCartao,
''1900-01-01'' PrimVencimentoCartao,
0 VlrTotCartao,
VlrDin = round((T3a.LineTotal/T3.DocTotal)*(T11.SumApplied/T01.DocTotal) * T01.CashSum,2),
VlrTransf = 0,
VlrCredit = 0,
VlrBol = 0,
VlrCH = 0,
VlrCart = 0,
VlrDev = 0,
VlrBLI = 0
FROM [UNION_ALL_BASES]..OVPM T01 with (nolock)
INNER JOIN [UNION_ALL_BASES]..VPM2 T11 with (nolock) ON T01.DocEntry = T11.DocNum and T01.UnionAll_Empresa = T11.UnionAll_Empresa
INNER JOIN [UNION_ALL_BASES]..PCH6 T2 with (nolock) ON T11.DocEntry = T2.DocEntry and T11.InstId = T2.InstlmntID and T11.UnionAll_Empresa = T2.UnionAll_Empresa
INNER JOIN [UNION_ALL_BASES]..OPCH T3 with (nolock) ON T2.DocEntry = T3.DocEntry and T2.UnionAll_Empresa = T3.UnionAll_Empresa
INNER JOIN [UNION_ALL_BASES]..PCH1 T3a with (nolock) ON T3.DocEntry = T3a.DocEntry and T3.UnionAll_Empresa = T3a.UnionAll_Empresa
LEFT JOIN [UNION_ALL_BASES]..OOCR T3b with (nolock) ON T3a.OcrCode2 = T3b.OcrCode and T3a.UnionAll_Empresa = T3b.UnionAll_Empresa
INNER JOIN [UNION_ALL_BASES]..OSLP T4 with (nolock) ON T3.SlpCode = T4.SlpCode and T4.UnionAll_Empresa = T4.UnionAll_Empresa
WHERE T11.InvType = ''18''
AND T01.Canceled <> ''Y''
AND T01.CashSum > 0
'
exec ('insert into #RelContasPagar ' + #vQuery)
Am I doing something Wrong?
Here's a problem in one of your join conditions:
and T4.UnionAll_Empresa = T4.UnionAll_Empresa
T4 to T4!
I really feel this question is beyond me but I'll propose something we're doing on a data warehouse project I'm working on. In addition to the standard ID primary key that we have on each table, in a number of cases we've added an additional key that we call the BK (Business Key) that we try to ensure is unique. The usage is a little different from a standard ID key because the BK is a string that has business related information embedded in it. I could see you using it to have a 'pseudo' primary key that could also tell you which server was the source for the row of data you've retrieved.
This may seem lame but it's all I could come up with.