How can I add a sub-query to this cursor? - sql

I tried to add a sub query (StoCount) to the following cursor:
DECLARE trans_cur CURSOR FOR
SELECT b.TransportNumber,
SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed,
COUNT(*) AS Total,
SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
(SELECT COUNT(*) FROM StorageTransportOrderItem WHERE DeliveryNumber = a.DeliveryNumber AND DeliveryItemNumber = a.DeliveryItemNumber) As StoCount
FROM DeliveryItem a
INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
WHERE a.StorageLocationNumber IS NOT NULL
AND a.Deleted <> 1
AND c.CommissioningArea LIKE #commissioningArea
AND d.TransportStatus < 70
GROUP BY b.TransportNumber
but when I always get the error message:
Msg 8120, Level 16, State 1, Procedure sp_CalculateTransportProgress,
Line 41 Column 'DeliveryItem.DeliveryNumber' is invalid in the select
list because it is not contained in either an aggregate function or
the GROUP BY clause. Msg 8120, Level 16, State 1, Procedure
sp_CalculateTransportProgress, Line 41 Column
'DeliveryItem.DeliveryItemNumber' is invalid in the select list
because it is not contained in either an aggregate function or the
GROUP BY clause.
My goal is to add this single column (StoCount) to the cursor without modifying the query too much.
Is that possible?

You could move the correlated subquery to a cross apply
SELECT b.TransportNumber,
SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed,
COUNT(*) AS Total,
SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
MAX(e.Freq) AS StoCount
FROM DeliveryItem a
INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
CROSS APPLY (
SELECT COUNT(*) freq FROM StorageTransportOrderItem s
WHERE s.DeliveryNumber = a.DeliveryNumber AND s.DeliveryItemNumber = a.DeliveryItemNumber
) e
WHERE a.StorageLocationNumber IS NOT NULL
AND a.Deleted <> 1
AND c.CommissioningArea LIKE #commissioningArea
AND d.TransportStatus < 70
GROUP BY b.TransportNumber
Edit by xsl:
I had to modify the query a bit, so that it returned the correct results for my database:
SELECT b.TransportNumber,
SUM(CASE WHEN a.DeliveryItemStatus = 'C' OR a.DeliveryItemStatus = 'V' THEN 1 ELSE 0 END) AS Completed,
COUNT(*) AS Total,
SUM(CASE WHEN a.DeliveryItemStatus = 'F' THEN 1 ELSE 0 END) AS Missing,
SUM(e.Freq) AS StoCount
FROM DeliveryItem a
INNER JOIN TransportItem b on a.DeliveryNumber = b.DeliveryNumber
INNER JOIN Material c on a.MaterialNumber = c.MaterialNumber
INNER JOIN Transport d on b.TransportNumber = d.TransportNumber
CROSS APPLY (
SELECT COUNT(1) freq FROM StorageTransportOrderItem s
WHERE
s.DeliveryNumber = a.DeliveryNumber
AND s.DeliveryItemNumber = a.DeliveryItemNumber
AND s.MaterialNumber = a.MaterialNumber
) e
WHERE a.StorageLocationNumber IS NOT NULL
AND a.Deleted <> 1
AND c.CommissioningArea LIKE #commissioningArea
AND d.TransportStatus < 70
GROUP BY b.TransportNumber

Related

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,

Sum values are inflated when I join another table

I have two queries that return the result sets I want, it is one row per user per day. The problem is that when I try to join the two queries, by userid, I get inflated results because the user is in the table multiple times for each day. How do I join them and avoid having the inflated results?
**Query 1**
SELECT AAL.UserID
, SUM(AAL.Dur)/60 AS 'LIM'
, SUM(CASE When AAL.DUR = 'av' then AAL.Dur/60
Else 0 END) AS 'AVAIL'
FROM WG
INNER JOIN AAL
on WG.UserID=AAL.UserID
and WG.SiteID=AAL.SiteID
WHERE WG.WG = 'OP'
AND DATEDIFF(day,AAL.Date,GETDATE()) = 1
GROUP BY AAL.UserID
**Query 2**
SELECT R.UserID
, SUM(CASE When R.StID = 4 then 1
Else 0 End) AS 'Rf Ct'
FROM R
INNER JOIN WG
on R.UserID = WG.UserID
WHERE WG.WG = 'OP'
AND DATEDIFF(day,R.Date,GETDATE()) = 1
GROUP BY R.UserID
**JOIN ATTEMPT**
SELECT AAL.UserID
, SUM(AAL.Dur)/60 AS 'LIM'
, SUM(CASE When AAL.DUR = 'av' then AAL.Dur/60
Else 0 END) AS 'AVAIL'
, SUM(CASE When R.StID = 4 then 1
Else 0 End) AS 'Rf Ct'
FROM WG
INNER JOIN AAL
on WG.UserID=AAL.UserID
and WG.SiteID=AAL.SiteID
INNER JOIN R
on AAL.UserID=R.UserID
WHERE WG.WG = 'OP'
AND DATEDIFF(day,AAL.Date,GETDATE()) = 1
GROUP BY AAL.UserID
You are not using WB in the query. So, just use exists or in:
SELECT R.UserID, SUM(CASE When R.StID = 4 then 1 Else 0 End) AS 'Rf Ct'
FROM R
WHERE DATEDIFF(day, R.Date, GETDATE()) = 1 AND
EXISTS (SELECT 1 FROM WB WHERE R.UserID = WG.UserID AND WG.WG = 'OP')
GROUP BY R.UserID;
You should understand the reason why the number gets multiplied -- multiple rows in WG correspond to a single R.ID.

Complex Case Statement Issue - Oracle SQL

Wrote the query below, but am getting multiplied amounts because the aggregation needs to occur before the case statements. Would love some advice on the best way to structure this.
Select Store, CUSTID, CUST.ID_CUST,
Sum(
CASE
WHEN Cust_Gift.Code_Status = 'C' AND Gift_Item.FLAG_STORE_LOC = 'N'
THEN Cust_Gift.AMT_PAID ELSE 0
END) GiftAmt,
Sum(
CASE WHEN Cust_Gift.Code_Status = 'C' AND Gift_Item.FLAG_STORE_LOC = 'Y'
THEN Cust_Gift.AMT ELSE 0
END) CustGiftAmt,
Sum(
CASE WHEN Cust_Coupon.Code_Status = 'C'
THEN Cust_Coupon.AMT
ELSE 0
END) CouponAmt,
Sum(CASE WHEN Cust_Sports.Status = 'C'
THEN Cust_Sports.AMT
ELSE 0
END) SportsAmt
FROM CUST
LEFT OUTER JOIN CUST_GIFT
ON CUST.ID_CUST = CUST_GIFT.ID_CUST
LEFT OUTER JOIN CUST_COUPON
ON CUST.ID_CUST = CUST_COUPON.ID_CUST
LEFT OUTER JOIN CUST_SPORTS
ON CUST.ID_CUST = CUST_SPORTS.ID_CUST
INNER JOIN GIFT_ITEM
ON CUST_GIFT.ID_GIFT_ITEM = GIFT_ITEM.ID_GIFT_ITEM
WHERE (STORE = 'M669098' OR STORE = 'M66923434' )
Group by CustID, Store, CUST.ID_CUST
This is one way you could do it:
SELECT cust.store,
cust.custid,
cust.id_cust,
gift.giftamt,
gift.custgift,
cpn.couponamt,
sprt.sportsamt
FROM cust
LEFT OUTER JOIN (SELECT id_cust,
SUM(CASE WHEN cg.code_status = 'C' AND gi.flag_store_loc = 'N' THEN cg.amt_paid END) giftamt,
SUM(CASE WHEN cg.code_status = 'C' AND gi.flag_store_loc = 'Y' THEN cg.amt_paid END) custgiftamt
FROM cust_gift cg
INNER JOIN gift_item gi ON cg.id_gift_item = gi.id_gift_item) gift ON cust.id_cust = gift.id_cust
LEFT OUTER JOIN (SELECT id_cust,
SUM(CASE WHEN code_status = 'C' THEN amt END) couponamt
FROM cust_coupon) cpn ON cust.id_cust = cpn.id_cust
LEFT OUTER JOIN (SELECT id_cust,
SUM(CASE WHEN status = 'C' THEN amt END) sportsamt
FROM cust_sports) sprt ON cust.id_cust = sprt.id_cust
WHERE (STORE = 'M669098' OR STORE = 'M66923434');

SQL Server Converting Rows to Columns

I am currently extracting data using 3 different tables, and below is the output.
Current Result:
Query Used:
SELECT
dbo.TableB.TrackingID, dbo.TableA.FinancialID,
dbo.TableA.ParcelCode, dbo.TableA.TotalAmount,
dbo.TableB.FinanceType, dbo.TableB.TransactionType,
dbo.TableC.CustID
FROM
dbo.TableA
INNER JOIN
dbo.TableB ON dbo.TableA.FinancialID = dbo.TableB.FinancialID
INNER JOIN
dbo.TableC ON dbo.TableB.TrackingID = dbo.TableC.TrackingID
WHERE
(dbo.TableB.TrackingID = '17006218AU')
I would like to have the following output:
Desired Output:
You can get the output you desire with grouping and some CASE statements inside SUM aggregate functions:
SELECT
dbo.TableB.TrackingID,
dbo.TableA.ParcelCode,
dbo.TableC.CustID,
SUM(CASE WHEN dbo.TableB.FinanceType = 'Invoice' THEN dbo.TableA.TotalAmount ELSE 0 END) AS TotalAmount,
SUM(CASE WHEN dbo.TableB.FinanceType = 'Invoice' AND TransType='Card' THEN dbo.TableA.TotalAmount ELSE 0 END) AS CardInvoice,
SUM(CASE WHEN dbo.TableB.FinanceType = 'Invoice' AND TransType='Cash' THEN dbo.TableA.TotalAmount ELSE 0 END) AS CashInvoice,
SUM(CASE WHEN dbo.TableB.FinanceType = 'PaymentRecepit' THEN dbo.TableA.TotalAmount ELSE 0 END) AS CardPaymentRecepit
FROM dbo.TableA
INNER JOIN dbo.TableB ON dbo.TableA.FinancialID = dbo.TableB.FinancialID
INNER JOIN dbo.TableC ON dbo.TableB.TrackingID = dbo.TableC.TrackingID
WHERE
dbo.TableB.TrackingID = '17006218AU'
GROUP BY
dbo.TableB.TrackingID,
dbo.TableA.ParcelCode,
dbo.TableC.CustID

Invalid column name error while using left join

I am getting Invalid column name 'PostId' error while executing the following query
Select a.SuburbDiscussionID,SUM((CASE WHEN b.postcnt IS NULL THEN 0 ELSE b.postcnt END) + (CASE WHEN c.replycnt IS NULL THEN 0 ELSE c.replycnt END)) AS TotCount
from SuburbDiscussions a
left join (SELECT COUNT(*) as postcnt,Posts.DiscussionId FROM Posts
GROUP BY Posts.DiscussionId) b on a.DiscussionId = b.DiscussionId
left join (SELECT COUNT(*) as replycnt,PostComments.PostId FROM PostComments
GROUP BY PostComments.PostId) c on b.PostId = c.PostId
where a.IsDelete = 0 and a.UserID != 33
Group by a.SuburbDiscussionID
ORDER BY TotCount
Why PostId column not detecting in my query?