SQL Server - 2008 : Nested Select, need improve execution faster? - sql

Here the problem:
First I have a nested query, for which I need to improve the execution time and make it faster. Imagine 47 seconds at first time and second time was 46 / 45 second. Second was running by cache (the second execution always faster than first time but not this).
Second that query uses SUM, CAST, CASE in each sub select. Can't dodge that
Third I read some another solution from internet using OPTION (FAST 500).
Here the example :
SELECT [cutomerSection],
SUM(DEBIT) AS DEBIT,
SUM(CREDIT) AS CREDIT,
SUM([OTHERS]) AS 'OTHERS'
FROM
(-- SECTOR A
SELECT cb.paymentGrp AS 'cutomerSection',
CASE
WHEN j.paymentStat = 'DEBIT' THEN SUM(CAST(ISNULL(isnull(qty, 1)*(100-disc)*d.adm/100, 0) AS INT)) + SUM(CAST(ISNULL(isnull(qty, 1)*(100-disc)*(d.fee-d.adm)/100, 0) AS INT))
ELSE 0
END AS 'DEBIT',
CASE
WHEN j.paymentStat = 'CREDIT' THEN SUM(CAST(ISNULL(isnull(qty, 1)*(100-disc)*d.adm/100, 0) AS INT)) + SUM(CAST(ISNULL(isnull(qty, 1)*(100-disc)*(d.fee-d.adm)/100, 0) AS INT))
ELSE 0
END AS 'CREDIT',
CASE
WHEN (j.paymentStat = ''
OR j.paymentStat IS NULL) THEN SUM(CAST(ISNULL(isnull(qty, 1)*(100-disc)*d.adm/100, 0) AS INT)) + SUM(CAST(ISNULL(isnull(qty, 1)*(100-disc)*(d.fee-d.adm)/100, 0) AS INT))
ELSE 0
END AS 'OTHERS'
FROM tbactDetail d WITH(NOLOCK)
LEFT JOIN tbsectorSection j WITH(NOLOCK) ON d.tranCode = j.tranCode
LEFT JOIN tbact t ON (d.actCode=t.actCode
AND t.sectorCode = j.sectorCode)
LEFT JOIN tbCustomer c WITH(NOLOCK) ON c.custCode=j.custCode
LEFT JOIN tbfrontDesk a WITH(NOLOCK) ON a.struckNo=j.struk
LEFT JOIN tbpaymentList cb WITH(NOLOCK) ON cb.paymentK = a.paymentK
LEFT JOIN tbleading dc ON dc.leadCode = j.leadCode
LEFT JOIN tbsector p ON j.sectorCode = p.sectorCode
WHERE (j.deleted IS NULL
OR j.deleted = 0)
AND a.status = 'FINISH'
AND (j.tranDate BETWEEN '2018-11-01 00:00:00' AND '2018-11-01 23:59:59')
GROUP BY cb.paymentGrp,
j.paymentStat
UNION ALL -- SECTOR PARK
SELECT cb.paymentGrp AS 'cutomerSection',
CASE
WHEN t.paymentStat = 'DEBIT' THEN SUM(CAST(isnull(d.rate*d.qty*(100-disc)/100, 0) AS INT))
ELSE 0
END AS 'DEBIT',
CASE
WHEN t.paymentStat = 'CREDIT' THEN SUM(CAST(isnull(d.rate*d.qty*(100-disc)/100, 0) AS INT))
ELSE 0
END AS 'CREDIT',
CASE
WHEN (t.paymentStat = ''
OR t.paymentStat IS NULL) THEN SUM(CAST(isnull(d.rate*d.qty*(100-disc)/100, 0) AS INT))
ELSE 0
END AS 'OTHERS'
FROM tbparkDetail d
LEFT JOIN tbTranPark t ON d.tranCode = t.tranCode
JOIN tbsectorSection j ON t.strukPoli = j.struk
LEFT JOIN tbCustomer c WITH(NOLOCK) ON c.custCode=j.custCode
LEFT JOIN tbfrontDesk a WITH(NOLOCK) ON a.struckNo=j.struk
JOIN tbpaymentList cb ON a.paymentK = cb.paymentK
LEFT JOIN tbleading dc ON dc.leadCode=j.leadCode
LEFT JOIN tbsector p ON j.sectorCode=p.sectorCode
WHERE (j.deleted IS NULL
OR j.deleted=0)
AND (t.strukPoli IS NOT NULL
OR t.strukPoli <> ''
OR t.strukPoli <> '--')
AND a.status = 'FINISH'
AND (j.tranDate BETWEEN '2018-11-01 00:00:00' AND '2018-11-01 23:59:59')
GROUP BY cb.paymentGrp,
t.paymentStat
UNION ALL -- SECTOR FRONT
SELECT cb.paymentGrp AS 'cutomerSection',
CASE
WHEN t.paymentStat = 'DEBIT' THEN SUM(CAST(isnull(d.rate*(100-disc)/100, 0) AS INT))
ELSE 0
END AS 'DEBIT',
CASE
WHEN t.paymentStat = 'CREDIT' THEN SUM(CAST(isnull(d.rate*(100-disc)/100, 0) AS INT))
ELSE 0
END AS 'CREDIT',
CASE
WHEN (t.paymentStat = ''
OR t.paymentStat IS NULL) THEN SUM(CAST(isnull(d.rate*(100-disc)/100, 0) AS INT))
ELSE 0
END AS 'OTHERS'
FROM tbDetailRadioterapi d
LEFT JOIN tbtranFront t ON d.tranCode = t.tranCode
LEFT JOIN tbsectorSection j ON t.strukPoli = j.struk
LEFT JOIN tbCustomer c WITH(NOLOCK) ON c.custCode=j.custCode
LEFT JOIN tbfrontDesk a WITH(NOLOCK) ON a.struckNo = j.struk
LEFT JOIN tbpaymentList cb ON a.paymentK = cb.paymentK
LEFT JOIN tbleading dc ON dc.leadCode=j.leadCode
LEFT JOIN tbsector p ON j.sectorCode=p.sectorCode
WHERE (t.deleted IS NULL
OR t.deleted=0)
AND (strukPoli IS NOT NULL
OR strukPoli <>''
OR strukPoli <>'--')
AND a.status='FINISH'
AND (j.tranDate BETWEEN '2018-11-01 00:00:00' AND '2018-11-01 23:59:59')
GROUP BY cb.paymentGrp,
t.paymentStat) AS a
GROUP BY [cutomerSection]
Third using option (fast 500), I don't know why but always got error :
Incorect Syntax near OPTION
PS : Sorry for my bad English

Related

The SQL Server query is taking too long to load the data

The below query is actually a view which is being used to display the cash payment report. But it is taking too much of time to load the data
SELECT
Billing_AccountPaymentDate.DueDate,
SUM(Billing_AccountCharge.NetAmount) AS NetCharges,
ISNULL(SUM(AccountChargePayment.SchoolPayments + AccountChargePayment.SchoolRemittances + AccountChargePayment.SchoolRemittancesPending), 0) / SUM(Billing_AccountCharge.NetAmount) AS PercentCollected,
SUM(Billing_AccountCharge.NetAmount - ISNULL(AccountChargePayment.SchoolPayments + AccountChargePayment.SchoolRemittances + AccountChargePayment.SchoolRemittancesPending, 0)) AS RemainingBalance,
Billing_AccountPaymentDate.RemittanceEffectiveDate,
Billing_Account.SchoolId,
ISNULL(SUM(AccountChargePayment.SchoolPayments), 0) AS SchoolPayments,
ISNULL(SUM(AccountChargePayment.SchoolRemittances), 0) AS SchoolRemittances,
ISNULL(SUM(AccountChargePayment.SchoolRemittancesPending), 0) AS SchoolRemittancesPending,
Billing_Account.SchoolYearId,
ISNULL(SUM(AccountChargePayment.SchoolPayments + AccountChargePayment.SchoolRemittances), 0) AS TotalReceipts
FROM
Billing_AccountCharge
INNER JOIN
Billing_AccountInvoice ON
Billing_AccountInvoice.AccountInvoiceId = Billing_AccountCharge.AccountInvoiceId
INNER JOIN
Billing_Account ON
Billing_Account.AccountId = Billing_AccountInvoice.AccountId
INNER JOIN
Billing_PaymentMethod ON
Billing_PaymentMethod.PaymentMethodId = CASE WHEN Billing_AccountInvoice.AutomaticPaymentEligible = 1 THEN Billing_Account.PaymentMethodId ELSE 3 END -- Send Statements
INNER JOIN
Billing_AccountPaymentDate ON
Billing_AccountPaymentDate.AccountPaymentMethodId = Billing_PaymentMethod.AnticipatedAccountPaymentMethodId AND
Billing_AccountPaymentDate.DueDate = Billing_AccountInvoice.DueDate AND
Billing_AccountPaymentDate.HoldForFee = Billing_Account.HoldPaymentForFee
INNER JOIN
Billing_ChargeItem ON
Billing_ChargeItem.ChargeItemId = Billing_AccountCharge.ChargeItemId
LEFT OUTER JOIN
(
SELECT
Billing_AccountChargePayment.AccountChargeId,
SUM(CASE WHEN Billing_AccountPayment.AccountPaymentTypeId = 9 THEN Billing_AccountChargePayment.Amount ELSE 0 END) AS SchoolPayments,
SUM(CASE WHEN Billing_AccountChargePayment.SchoolRemittanceId IS NOT NULL THEN Billing_AccountChargePayment.Amount ELSE 0 END) AS SchoolRemittances,
SUM(CASE WHEN Billing_AccountChargePayment.SchoolRemittanceId IS NULL AND Billing_AccountPayment.AccountPaymentTypeId <> 9 THEN Billing_AccountChargePayment.Amount ELSE 0 END) AS SchoolRemittancesPending
FROM
Billing_AccountChargePayment
INNER JOIN
Billing_AccountPayment ON
Billing_AccountPayment.AccountPaymentId = Billing_AccountChargePayment.AccountPaymentId
GROUP BY
Billing_AccountChargePayment.AccountChargeId
) AccountChargePayment ON
AccountChargePayment.AccountChargeId = Billing_AccountCharge.AccountChargeId
WHERE
Billing_AccountInvoice.AccountInvoiceStatusId <> 4 AND -- Voided
Billing_ChargeItem.RemitToSchool = 1
AND Billing_Account.[SchoolId] = 6 --hard code in a school with data
AND Billing_Account.[SchoolYearId] = 12 --hard code in a school year with data
GROUP BY
Billing_AccountPaymentDate.DueDate,
Billing_AccountPaymentDate.RemittanceEffectiveDate,
Billing_Account.SchoolId,
Billing_Account.SchoolYearId
HAVING
SUM(Billing_AccountCharge.NetAmount) <> 0
order by Billing_AccountPaymentDate.DueDate ASC
It looks like the inner query in the left join is taking too much of time, both the tables already have non clustered index, I tried taking those tables outside but the data is not accurate
Use CTE instead of subquery and do all calculation there instead of in Left outer join. Moreover, use with(nolock) whenever you fetch data. Still your query is taking much more time then You should implement proper indexing.
WITH PaymentData AS (
SELECT
acp.AccountChargeId,
SUM(
CASE
WHEN ap.AccountPaymentTypeId = 9 THEN acp.Amount
ELSE 0
END
) AS SchoolPayments,
SUM(
CASE
WHEN acp.SchoolRemittanceId IS NOT NULL THEN acp.Amount
ELSE 0
END
) AS SchoolRemittances,
SUM(
CASE
WHEN acp.SchoolRemittanceId IS NULL AND ap.AccountPaymentTypeId <> 9 THEN acp.Amount
ELSE 0
END
) AS SchoolRemittancesPending
FROM
Billing_AccountChargePayment acp WITH(NOLOCK)
INNER JOIN Billing_AccountPayment ap WITH(NOLOCK) ON acp.AccountPaymentId = ap.AccountPaymentId
GROUP BY
acp.AccountChargeId
)
SELECT
apd.DueDate,
SUM(ac.NetAmount) AS NetCharges,
COALESCE(
SUM(pd.SchoolPayments + pd.SchoolRemittances + pd.SchoolRemittancesPending),
0
) / SUM(ac.NetAmount) AS PercentCollected,
SUM(ac.NetAmount - COALESCE(pd.SchoolPayments, 0) - COALESCE(pd.SchoolRemittances, 0) - COALESCE(pd.SchoolRemittancesPending, 0)) AS RemainingBalance,
apd.RemittanceEffectiveDate,
a.SchoolId,
COALESCE(SUM(pd.SchoolPayments), 0) AS SchoolPayments,
COALESCE(SUM(pd.SchoolRemittances), 0) AS SchoolRemittances,
COALESCE(SUM(pd.SchoolRemittancesPending), 0) AS SchoolRemittancesPending,
a.SchoolYearId,
COALESCE(SUM(pd.SchoolPayments + pd.SchoolRemittances), 0) AS TotalReceipts
FROM
Billing_AccountCharge ac WITH(NOLOCK)
INNER JOIN Billing_AccountInvoice ai WITH(NOLOCK) ON ac.AccountInvoiceId = ai.AccountInvoiceId
INNER JOIN Billing_Account a WITH(NOLOCK) ON ai.AccountId = a.AccountId
INNER JOIN Billing_PaymentMethod pm WITH(NOLOCK) ON pm.PaymentMethodId = CASE
WHEN ai.AutomaticPaymentEligible = 1 THEN a.PaymentMethodId
ELSE 3
END
INNER JOIN Billing_AccountPaymentDate apd WITH(NOLOCK) ON
apd.AccountPaymentMethodId = pm.AnticipatedAccountPaymentMethodId AND
apd.DueDate = ai.DueDate AND
apd.HoldForFee = a.HoldPaymentForFee
INNER JOIN Billing_ChargeItem ci WITH(NOLOCK) ON ac.ChargeItemId = ci.ChargeItemId
LEFT OUTER JOIN PaymentData pd WITH(NOLOCK) ON ac.AccountChargeId = pd.AccountChargeId
WHERE
ai.AccountInvoiceStatusId <> 4 AND
ci.RemitToSchool = 1 AND
a.SchoolId = 6 AND
a.SchoolYearId = 12
GROUP BY
apd.DueDate,
apd.RemittanceEffectiveDate,
a.SchoolId,
a.SchoolYearId
HAVING
SUM(ac.NetAmount) <> 0
ORDER BY
apd.DueDate ASC;

Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= orwhen the subquery is used as an expression

I am having this error message. I have tried many other ways but can't resolve the issue.
I would be really grateful if someone could look at this :
;WITH progression
AS
(
SELECT
w.CustomerID,
CASE WHEN SUM(CASE WHEN w.workflowoutcomeid = 8 THEN 1 ELSE 0 END) > 0 THEN 'Yes' ELSE 'No' END AS [PG01],
CASE WHEN SUM(CASE WHEN w.workflowoutcomeid = 11 THEN 1 ELSE 0 END) > 0 THEN 'Yes' ELSE 'No' END AS [PG03],
CASE WHEN SUM(CASE WHEN w.workflowoutcomeid = 14 THEN 1 ELSE 0 END) > 0 THEN 'Yes' ELSE 'No' END AS [PG04],
CASE WHEN SUM(CASE WHEN w.workflowoutcomeid = 17 THEN 1 ELSE 0 END) > 0 THEN 'Yes' ELSE 'No' END AS [PG05],
CASE WHEN SUM(CASE WHEN w.workflowoutcomeid = 9 THEN 1 ELSE 0 END) > 0 THEN 'Yes' ELSE 'No' END AS [in_work_review]
FROM
ABC.dbo.tblWorkflow w
WHERE
w.Deleted IS NULL
AND
w.workflowqueueid = 4
AND
w.workflowoutcomeid IN (8, 11, 14, 17, 9)
GROUP BY
w.CustomerID
),
contact_data
AS
(
SELECT
CustomerID, [Email], [Mobile], [Home]
FROM
(
SELECT
CustomerID,
CASE
WHEN ContactTypeID = 1 THEN 'Home'
WHEN ContactTypeID = 2 THEN 'Mobile'
WHEN ContactTypeID = 5 THEN 'Email'
END AS ContactTypeDescription,
ContactValue
FROM ABC.dbo.tblCustomerContact
WHERE ContactTypeID IN (1,2,5)
) base
PIVOT
(
MAX(ContactValue) FOR ContactTypeDescription IN ([Home],[Mobile],[Email])
) pvt
),
appointment
AS
(
SELECT
n.[Key] AS CustomerID,
MAX(CASE WHEN n.AppointmentStatusID IN (2,4) THEN n.ActionDate ELSE NULL END) AS [Last_Completed_Attended_Appointment],
MAX(CASE WHEN n.AppointmentStatusID = 1 THEN n.ActionDate ELSE NULL END) AS [Next Pending Appointment]
FROM ABC.dbo.tblNote n
WHERE n.AppointmentTypeID = 6 AND n.AppointmentStatusID IN (1,2,4)
GROUP BY n.[Key]
)
SELECT
m.Firstname + ' ' + m.Lastname AS [Manager],
u.Firstname + ' ' + u.Lastname AS [Adviser],
c.CustomerID,
c.GivenName + ' ' + c.FamilyName AS [Customer Name],
g.Gender,
e.EthnicityName AS Ethnicity,
com.CompanyName,
NULL AS DeliverySite,
d.[Name] AS District,
css.ServiceStatus,
contact_data.Email,
uad.Line1 AS AddressLine1,
uad.Line2 AS AddressLine2,
uad.Line3 AS AddressLine3,
uad.Postcode,
uad.AlternativePostcode,
uad.Town,
ISNULL(contact_data.mobile, contact_data.home) AS Phone,
c.StartDate,
(SELECT MIN(wh.MGCReviewerModifiedDate) AS [ST01_Approved_Date]
FROM ABC.dbo.tblWorkflow w
INNER JOIN ABC.dbo.tblWorkflowHistory wh
ON w.WorkflowID = wh.WorkflowID
WHERE wh.WorkflowQueueID = 4 AND wh.MGCReviewerModifiedDate IS NOT NULL
AND wh.Deleted IS NULL AND w.WorkflowOutcomeID = 1 AND w.WorkflowQueueID = 4
AND w.Deleted IS NULL AND w.CustomerID = c.CustomerID
GROUP BY w.WorkflowID, w.CustomerID) AS ST01_Approved_Date,
qual.LearningAimTitle,
qual.LearningAimCompletionStatus,
qual.LearningAimOutcomeStatus,
mwp.WorkExperienceTitle ,
mwp.WorkExperienceStartDate,
mwp.WorkExperienceEndDate,
mwp.learningaimcompletionstatus as [Work_Ex_CompletionStatus],
mwp.learningaimoutcomestatus as [Work_Ex_OutcomeStatus],
p.PG01 AS [PG01_Start(Job Start Approved/Claimed ?)],
p.in_work_review AS [PG01_In_work_review(Job Outcome Approved/Claimed ?)],
p.PG03 AS [PG03 – Education Approved / Claimed?],
p.PG04 AS [PG04 – Apprenticeship Approved / Claimed?],
p.PG05 AS [PG05– Apprenticeship Approved / Claimed?],
a.Last_Completed_Attended_Appointment,
a.[Next Pending Appointment],
FLOOR(DATEDIFF(day, c.DateOfBirth, GETDATE()) / 365.25) as CustomerAge
FROM ABC.dbo.tblCustomer c
LEFT JOIN ABC.dbo.tblUser u ON c.OwnerID = u.UserID
LEFT JOIN ABC.dbo.tblUser m ON u.ManagerID = m.UserID
LEFT JOIN ABC.dbo.tlkpGender g ON c.GenderID = g.GenderID
LEFT JOIN ABC.dbo.tlkpEthnicity e ON c.EthnicityID = e.EthnicityID
LEFT JOIN ABC.dbo.tblCompany com ON c.CompanyId = com.[CompanyID]
LEFT JOIN ABC.dbo.tblCustomerAddress cad ON c.CustomerID = cad.CustomerID AND cad.EffectiveTo IS NULL
LEFT JOIN ABC.dbo.tblUKAddress uad ON uad.UKaddressID = cad.UKaddressID
LEFT JOIN PostcodeESyNCS.dbo.tblPostcode po ON uad.Postcode = po.Postcode
LEFT JOIN PostcodeESyNCS.dbo.tlkpDistrict d ON po.DistrictId = d.DistrictId
LEFT JOIN ABC.dbo.tlkpCustomerServiceStatus css ON c.CustomerServiceStatusID = css.CustomerServiceStatusID
LEFT JOIN progression p ON c.CustomerID = p.CustomerID
LEFT JOIN contact_data ON c.CustomerID = contact_data.CustomerID
OUTER APPLY
(
SELECT TOP 1
l.learningaimid,
aim.LearningAimTitle,
aim.isfullqualification,
st.LearningAimCompletionStatus,
aos.LearningAimOutcomeStatus
FROM ABC.dbo.tbllearning l
LEFT JOIN ABC.dbo.tlkplearningaim aim on aim.learningaimid = l.learningaimid
LEFT JOIN ABC.dbo.tlkplearningaimcompletionstatus st on st.learningaimcompletionstatusid = l.learningaimcompletionstatusid
LEFT JOIN ABC.dbo.tlkpLearningAimOutcomeStatus aos on aos.learningaimoutcomestatusid = l.learningaimoutcomestatusid
WHERE aim.learningaimtypeid = 1 AND l.customerid = c.customerid
ORDER BY l.StartDate DESC
) qual
OUTER APPLY
(
SELECT TOP 1
l.learningaimid,
REPLACE(aim.LearningAimTitle,',',' ') as WorkExperienceTitle,
aim.isfullqualification,
st.LearningAimCompletionStatus,
outcome.LearningAimOutcomeStatus,
l.StartDate as WorkExperienceStartDate,
l.ActualEndDate as WorkExperienceEndDate
FROM ABC.dbo.tbllearning l
LEFT JOIN ABC.dbo.tlkplearningaim aim ON aim.learningaimid=l.learningaimid
LEFT JOIN ABC.dbo.tlkplearningaimcompletionstatus st ON st.learningaimcompletionstatusid=l.learningaimcompletionstatusid
LEFT JOIN ABC.dbo.tlkpLearningAimOutcomeStatus outcome ON outcome.learningaimoutcomestatusid= l.learningaimoutcomestatusid
WHERE aim.LearningAimID IN (SELECT la.LearningAimID
FROM ABC.dbo.tlkpLearningAim la
WHERE la.LearningAimTypeID = 2
and la.LearningAimTitle like '%Work%')
AND l.customerid = c.customerid
ORDER BY StartDate DESC
) AS mwp
LEFT JOIN appointment a ON c.CustomerID = a.CustomerID
WHERE
c.Deleted IS NULL
I am getting the following error:
Msg 512, Level 16, State 1, Line 2
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Warning: Null value is eliminated by an aggregate or other SET operation.
The only place where I see that this could be happening is the definition of ST01_Approved_Date:
(SELECT MIN(wh.MGCReviewerModifiedDate) AS [ST01_Approved_Date]
FROM ABC.dbo.tblWorkflow w JOIN
ABC.dbo.tblWorkflowHistory wh
ON w.WorkflowID = wh.WorkflowID
WHERE wh.WorkflowQueueID = 4 AND wh.MGCReviewerModifiedDate IS NOT NULL AND
wh.Deleted IS NULL AND w.WorkflowOutcomeID = 1 AND w.WorkflowQueueID = 4 AND
w.Deleted IS NULL AND w.CustomerID = c.CustomerID
GROUP BY w.WorkflowID, w.CustomerID
) AS ST01_Approved_Date,
A correlated subquery should not contain GROUP By for exactly this reason. I don't know what the logic would be, but there should probably be a condition on w.WorkFlowId to the outer query, something like:
(SELECT MIN(wh.MGCReviewerModifiedDate) AS [ST01_Approved_Date]
FROM ABC.dbo.tblWorkflow w JOIN
ABC.dbo.tblWorkflowHistory wh
ON w.WorkflowID = wh.WorkflowID
WHERE wh.WorkflowQueueID = 4 AND wh.MGCReviewerModifiedDate IS NOT NULL AND
wh.Deleted IS NULL AND w.WorkflowOutcomeID = 1 AND w.WorkflowQueueID = 4 AND
w.Deleted IS NULL AND w.CustomerID = c.CustomerID AND
w.workflowID = <outer query reference>.WorkflowId
) AS ST01_Approved_Date,

Using an array in conditional summation with grouping

I have the sql query thats work fine
SELECT
CAST(L.CreationUtcDateTime AS DATE),
SUM(L.Profit),
SUM(CASE WHEN (L.Network = 0 OR L.Network = 1) THEN L.Profit ELSE 0 END),
SUM(CASE WHEN (L.Network != 0 AND L.Network != 1) THEN L.Profit ELSE 0 END)
FROM
[dbo].[Leads] L WITH (NOLOCK)
LEFT JOIN [dbo].[Transactions] S WITH (NOLOCK) ON L.TransactionId = S.Id
GROUP BY
CAST(L.CreationUtcDateTime AS DATE);
I need to make it more generic by using variables instead of hard-coded constants.
I changed the query to:
DECLARE #matchNetworks TABLE (id int)
INSERT #matchNetworks(id) VALUES (0),(1)
SELECT
CAST(L.CreationUtcDateTime AS DATE),
SUM(L.Profit),
SUM(CASE WHEN (L.Network in (SELECT ID from #matchNetworks)) THEN L.Profit ELSE 0 END),
SUM(CASE WHEN (L.Network not in (SELECT ID from #matchNetworks)) THEN L.Profit ELSE 0 END)
FROM
[dbo].[Leads] L WITH (NOLOCK)
LEFT JOIN [dbo].[Transactions] S WITH (NOLOCK) ON L.TransactionId = S.Id
GROUP BY
CAST(L.CreationUtcDateTime AS DATE);
And now i have an error:
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
How can I use the predefined array of network ids in my query to avoid an error?
Move the comparison to the FROM clause using a LEFT JOIN:
SELECT CAST(L.CreationUtcDateTime AS DATE),
SUM(L.Profit),
SUM(CASE WHEN mn.ID IS NOT NULL THEN L.Profit ELSE 0 END),
SUM(CASE WHEN mn.ID IS NULL THEN L.Profit ELSE 0 END)
FROM [dbo].[Leads] L LEFT JOIN
[dbo].[Transactions] S
ON L.TransactionId = S.Id LEFT JOIN
#matchNetworks mn
ON mn.ID = l.Network
GROUP BY CAST(L.CreationUtcDateTime AS DATE);

PL/SQL to T-SQL conversion error

Working to convert the following statement to T-SQL from PL/SQL (Work in progress). However I've run into an error in SQL Server.
SELECT COUNT(*) OVER() AS RW_CNT
,COUNT(*) OVER( PARTITION BY(P.PLACEMENT_HISTORY_ID)) AS DP_CNT
,P.PLACEMENT_HISTORY_ID AS DD_PLCMT_HIST_ID
,U.ES_PARTICIPANT_KEY
,A.ES_PARTICIPANT_ATTR_KEY
,ISNULL(CENTER.ES_ORG_KEY, 0) AS ES_CENTER_ORG_KEY
,ISNULL(O.ES_ORG_KEY, 0) AS ES_LOCAL_UNIT_KEY
,ISNULL(STK.ES_ORG_KEY, 0) AS ES_STAKE_UNIT_KEY
,ISNULL(PED.ES_EMPLOYER_KEY, 0) AS ES_PLCMT_EMPLOYER_KEY
,ISNULL(PD.ES_PARTICIPANT_KEY, 0) AS ES_CREATOR_USERS_KEY
,CONVERT(VARCHAR(8), CONVERT(DATE,P.PLACED_DATE), 112) AS PLACED_DATE_KEY
,CONVERT(VARCHAR(8), CONVERT(DATE,P.CREATED_DATE), 112) AS PLCMT_RECORDED_DATE_KEY
,CONVERT(DATETIME, CONVERT(DATE,GETDATE())) AS LOAD_DATE
,1 AS PLCMT_CNT
,CASE WHEN P.PLACEMENT_TYPE = 0 THEN 1 ELSE 0 END AS OBTAIN_JOB_CNT
,CASE WHEN P.PLACEMENT_TYPE = 2 THEN 1 ELSE 0 END AS ENROLL_SBA_CNT
,CASE WHEN P.PLACEMENT_TYPE = 3 THEN 1 ELSE 0 END AS STARTED_BUSINESS_CNT
,CASE WHEN P.PLACEMENT_TYPE = 1 THEN 1 ELSE 0 END AS BEGIN_EDU_TRAINING_CNT
,U.MEMBER_1_0_FLAG AS MEMBER_CNT
,CASE WHEN P.DI_FUNDED = 'Y' THEN 1 ELSE 0 END AS DI_FUNDED_CNT
,ISNULL(DTP.DAYS_TO_PLCMT, PF.DAYS_TO_PLCMT) AS DAYS_TO_PLCMT
,ISNULL(LD.LOCAL_COUNCIL_KEY, isnull(OVERRIDE_LC.Local_Council_Key, 1)) AS LOCAL_COUNCIL_KEY
FROM DSS_ERS_STAGE.ES_W_PLCMT_HIST P
LEFT JOIN DSS_ERS_STAGE.ES_PARTICIPANT_DIM U ON (P.CANDIDATE_ID =
U.CANDIDATE_ID)
LEFT JOIN DSS_ERS_STAGE.ES_W_USER WU ON (U.USER_ID = WU.USER_ID)
LEFT JOIN DSS_ERS_STAGE.ES_ORG_DIM O ON (WU.HOME_UNIT_NUMBER =
O.UNIT_NUMBER AND O.ORG_TYPE_ID IN (7,8) AND O.ORG_STATUS_CODE = 1)
LEFT JOIN DSS_ERS_STAGE.ES_ORG_DIM STK ON (O.STK_DIST_ORG_ID = STK.ORG_ID
AND STK.ORG_TYPE_ID IN (5,6) AND STK.ORG_STATUS_CODE = 1)
LEFT JOIN DSS_ERS_STAGE.ES_ORG_DIM CENTER ON (O.RSC_CNTR_ORG_ID =
CENTER.ORG_ID AND (CENTER.ORG_TYPE_ID IN (60,61)) AND
(CENTER.ORG_STATUS_CODE =1))
LEFT JOIN DSS_ERS_STAGE.ES_PARTICIPANT_ATTR_DIM A ON (A.ID_AS_VARCHAR =
(ISNULL(U.PROF_VISIBLE_1_0_FLAG, '') +
ISNULL(U.PROF_STAFF_1_0_FLAG, '') +
ISNULL(U.DI_ASSOCIATE_1_0_FLAG, '') +
ISNULL(U.PEF_STUDENT_1_0_FLAG, '') +
ISNULL(0, '') +
ISNULL(U.BISHOP_REPORT_1_0_FLAG, '') +
ISNULL(U.PROFILE_ACTIVE_1_0_FLAG, '') +
ISNULL(U.MEMBER_1_0_FLAG, '') +
ISNULL(U.ACCELERATED_1_0_FLAG, '') +
ISNULL(CASE WHEN P.DI_FUNDED = 'Y' THEN
1 ELSE 0 END, '')))
LEFT JOIN DSS_ERS_STAGE.ES_PLCMT_EMPLOYER_DIM PED ON
(P.PLACEMENT_HISTORY_ID = PED.CAND_HIST_PLCMT_ID)
LEFT JOIN DSS_ERS_STAGE.ES_PARTICIPANT_DIM PD ON (P.CREATED_BY_USER =
PD.USER_ID)
LEFT JOIN DSS_ERS_STAGE.ES_W_DTP_MAPPING_SS DTP ON (P.PLACEMENT_HISTORY_ID =
DTP.PLACEMENT_HISTORY_ID)
LEFT JOIN DSS_ERS_STAGE.ES_PLACEMENT_FACT PF ON (P.PLACEMENT_HISTORY_ID =
PF.DD_PLCMT_HIST_ID)
LEFT JOIN DSS_ERS_STAGE.ES_LOCAL_COUNCIL_DIM LD ON (P.LOCAL_COUNCIL =
LD.LOCAL_COUNCIL_ID)
LEFT JOIN DSS_ERS_STAGE.ES_LOCAL_COUNCIL_DIM OVERRIDE_LC ON
(STK.LOCAL_COUNCIL = OVERRIDE_LC.LOCAL_COUNCIL_NAME)
--WHERE P.PLACEMENT_HISTORY_ID = 1215
GROUP BY
P.PLACEMENT_HISTORY_ID
,U.ES_PARTICIPANT_KEY
,A.ES_PARTICIPANT_ATTR_KEY
,CENTER.ES_ORG_KEY
,O.ES_ORG_KEY
,STK.ES_ORG_KEY
,CONVERT(VARCHAR(8), CONVERT(DATE,P.PLACED_DATE), 112)
,CONVERT(VARCHAR(8), CONVERT(DATE,P.CREATED_DATE), 112)
,CONVERT(DATETIME, CONVERT(DATE,GETDATE()))
,CASE WHEN P.PLACEMENT_TYPE = 0 THEN 1 ELSE 0 END
,CASE WHEN P.PLACEMENT_TYPE = 2 THEN 1 ELSE 0 END
,CASE WHEN P.PLACEMENT_TYPE = 3 THEN 1 ELSE 0 END
,CASE WHEN P.PLACEMENT_TYPE = 1 THEN 1 ELSE 0 END
,U.MEMBER_1_0_FLAG
,CASE WHEN P.DI_FUNDED = 'Y' THEN 1 ELSE 0 END
,PED.ES_EMPLOYER_KEY
,PD.ES_PARTICIPANT_KEY
,ISNULL(DTP.DAYS_TO_PLCMT, PF.DAYS_TO_PLCMT)
,ISNULL(LD.LOCAL_COUNCIL_KEY, isnull(OVERRIDE_LC.Local_Council_Key, 1))
I'm getting this error in SQL Server. It's fairly ambiguous. The resources I've found on the web haven't helped much in understanding what the issue is here.
Msg 164, Level 15, State 1, Line 55
Each GROUP BY expression must contain at least one column that is not an
outer reference.
*I'm adding this sentence because stackoverflow is telling me that my post is mostly code and that I need more details......
You get this error when you have a constant as a key in the GROUP BY. For some reason, that bothers SQL Server.
In your case, the "constant" appears to be:
CONVERT(DATETIME, CONVERT(DATE, GETDATE()))
Simply remove this from the GROUP BY keys.
(And, just for the record, each reference to GETDATE() is evaluated once per query, so it is a "constant" for this purpose.)

Summing two seperate queries into one value using UNION ALL clause

I have the following query (as part of a larger query). I am trying to get the sum results from 2 different data sets within a subquery but I am having trouble trying to encapsulate the two into 1 value. What I have is this:
(Select SUM('Invoiced MTD') from
((Select SUM(CASE WHEN SOH.LASDLVNUM_0 <> '' AND SOH.LASINVNUM_0 <> '' AND MONTH(SOH.SHIDAT_0) = MONTH(GETDATE()) THEN
(SOP.NETPRI_0 * SOQ.QTY_0 * SOH.CHGRAT_0) ELSE 0 END) as 'Invoiced MTD'
From x3v6.CICPROD.SORDER SOH
LEFT OUTER JOIN x3v6.CICPROD.BPCUSTOMER BPC on SOH.BPCORD_0 = BPC.BPCNUM_0
LEFT OUTER JOIN x3v6.CICPROD.SORDERQ SOQ on SOH.SOHNUM_0 = SOQ.SOHNUM_0
LEFT OUTER JOIN x3v6.CICPROD.SORDERP SOP on SOQ.SOHNUM_0 = SOP.SOHNUM_0 and SOQ.SOPLIN_0 = SOP.SOPLIN_0 and SOQ.SOQSEQ_0 = SOP.SOPSEQ_0
LEFT OUTER JOIN x3v6.CICPROD.ITMMASTER ITM on SOP.ITMREF_0 = ITM.ITMREF_0 ))
UNION ALL
((Select SUM(CASE WHEN SIH.INVTYP_0 = 2 and MONTH(SIH.ACCDAT_0) = MONTH(GETDATE()) THEN SID.AMTNOTLIN_0 * (-1) ELSE 0 END) as 'Invoiced MTD'
From x3v6.CICPROD.SINVOICE SIH
Left Outer Join x3v6.CICPROD.SINVOICED SID on SIH.NUM_0 = SID.NUM_0))
as 'T2',
But I am getting an error where the UNION ALL clauses is, and I can't figure it out. Basically I want to combine Sales credit memos with the sales order dollar totals from a seperate table.
Can anyone assist me with this?
What about this ?
Select SUM([Invoiced MTD]) from
(
Select SUM(CASE WHEN SOH.LASDLVNUM_0 <> '' AND SOH.LASINVNUM_0 <> '' AND MONTH(SOH.SHIDAT_0) = MONTH(GETDATE())
THEN (SOP.NETPRI_0 * SOQ.QTY_0 * SOH.CHGRAT_0) ELSE 0 END) as 'Invoiced MTD'
From x3v6.CICPROD.SORDER SOH
LEFT OUTER JOIN x3v6.CICPROD.BPCUSTOMER BPC on SOH.BPCORD_0 = BPC.BPCNUM_0
LEFT OUTER JOIN x3v6.CICPROD.SORDERQ SOQ on SOH.SOHNUM_0 = SOQ.SOHNUM_0
LEFT OUTER JOIN x3v6.CICPROD.SORDERP SOP on SOQ.SOHNUM_0 = SOP.SOHNUM_0 and SOQ.SOPLIN_0 = SOP.SOPLIN_0 and SOQ.SOQSEQ_0 = SOP.SOPSEQ_0
LEFT OUTER JOIN x3v6.CICPROD.ITMMASTER ITM on SOP.ITMREF_0 = ITM.ITMREF_0
UNION ALL
Select SUM(CASE WHEN SIH.INVTYP_0 = 2 and MONTH(SIH.ACCDAT_0) = MONTH(GETDATE())
THEN SID.AMTNOTLIN_0 * (-1) ELSE 0 END) as 'Invoiced MTD'
From x3v6.CICPROD.SINVOICE SIH
Left Outer Join x3v6.CICPROD.SINVOICED SID on SIH.NUM_0 = SID.NUM_0
)T
Does this work? I'm not sure exactly what is causing your issue, but you definitely don't need so many parenthesis. I would also recommend using something that formats/ beautifies your SQL. It's a great way to 1) keep your code looking consistent and 2) flesh out syntax errors.
SELECT SUM(x.invoiced_mtd)
FROM (SELECT SUM(CASE
WHEN soh.lasdlvnum_0 <> '' AND soh.lasinvnum_0 <> '' AND
MONTH(soh.shidat_0) = MONTH(getdate()) THEN
(sop.netpri_0 * soq.qty_0 * soh.chgrat_0)
ELSE
0
END) AS invoiced_mtd
FROM x3v6.cicprod.sorder soh
LEFT OUTER JOIN x3v6.cicprod.bpcustomer bpc
ON soh.bpcord_0 = bpc.bpcnum_0
LEFT OUTER JOIN x3v6.cicprod.sorderq soq
ON soh.sohnum_0 = soq.sohnum_0
LEFT OUTER JOIN x3v6.cicprod.sorderp sop
ON soq.sohnum_0 = sop.sohnum_0
AND soq.soplin_0 = sop.soplin_0
AND soq.soqseq_0 = sop.sopseq_0
LEFT OUTER JOIN x3v6.cicprod.itmmaster itm
ON sop.itmref_0 = itm.itmref_0
UNION ALL
SELECT SUM(CASE
WHEN sih.invtyp_0 = 2 AND
MONTH(sih.accdat_0) = MONTH(getdate()) THEN
sid.amtnotlin_0 * (-1)
ELSE
0
END)
FROM x3v6.cicprod.sinvoice sih
LEFT OUTER JOIN x3v6.cicprod.sinvoiced sid
ON sih.num_0 = sid.num_0) x;
Try using a CTE for the UNION query first. Here is a simplified example with the same structure as your query:
;with cteTest AS (
((select 2 as 'test'))
union all
((select 3 as 'test'))
)
select sum(test) from cteTest