So this is what i thought of doing but now the error i am getting is : Cannot use an aggregate or a subquery in an expression used for the group by list of a GROUP BY clause and not sure which part it means - the overall code i am trying to get open cases based on two different levels one is to return cases based on date range passed in and the other is to return cases based on just the begin date and before it.
Help will be great! :)
CODE:
SELECT
C.CaseNumber,
O.OfficeName,
CT.Description AS CaseType,
DATEADD(dd, 0, DATEDIFF(dd, 0, C.DateOpened)) AS DateOpened,
CR.Description AS Court,
CaseOfficeAppointment.OpenCases,
CaseOfficeAppointment.CloseCases
FROM
(
SELECT C.CaseId, O.OfficeId, CRT.CourtId,
(
SELECT COUNT(DISTINCT CD.CaseId)
FROM [Case] CD
INNER JOIN CaseOffice COD ON CD.CaseId = COD.CaseId
--INNER JOIN Court CR ON CD.CourtId = CR.CourtId
INNER JOIN Office OD ON COD.OfficeId = OD.OfficeId
LEFT OUTER JOIN CaseStatusChange CSC ON CD.CaseId = CSC.CaseId
--WHERE CR.CourtId = CRT.CourtId
WHERE OD.OfficeId = O.OfficeId
AND
( CD.DateOpened BETWEEN #BeginDate AND #EndDate
OR
CSC.DateReopened BETWEEN #BeginDate AND #EndDate
)
)AS OpenCases,
(
SELECT COUNT(DISTINCT CD.CaseId)
FROM [Case] CD
INNER JOIN CaseOffice COD ON CD.CaseId = COD.CaseId
--INNER JOIN Court CR ON CD.CourtId = CR.CourtId
INNER JOIN Office OD ON COD.OfficeId = OD.OfficeId
LEFT OUTER JOIN CaseStatusChange CSC ON CD.CaseId = CSC.CaseId
--WHERE CR.CourtId = CRT.CourtId
WHERE OD.OfficeId = O.OfficeId
AND
( CSC.DateClosed BETWEEN #BeginDate AND #EndDate
)
)AS CloseCases
FROM [Case] C
INNER JOIN [Appointment] A ON C.CaseId = A.CaseId
INNER JOIN [Office] O ON A.OfficeId = O.OfficeId
INNER JOIN [Court] CRT ON C.CourtId = CRT.CourtId
WHERE
-- Case was open (or reopened) during the date range
C.DateOpened BETWEEN #beginDate AND #endDate
OR
C.CaseId IN (SELECT CaseId FROM CaseStatusChange WHERE DateReopened BETWEEN #beginDate AND #endDate)
AND
-- Office had an appointment sometime during the date range
A.DateOn < #endDate AND (A.DateOff IS NULL OR A.DateOff BETWEEN #beginDate AND #endDate)
GROUP BY C.CaseId, O.OfficeId, CRT.CourtId,
(
SELECT OfficeId, SUM(CaseCount)AS Counts
FROM (
SELECT COUNT(C.CaseId) AS CaseCount,O.OfficeId
FROM [Case] C
INNER JOIN [Appointment] A ON C.CaseId = A.CaseId
INNER JOIN [Office] O ON A.OfficeId = O.OfficeId
WHERE C.DateCreated <= #BeginDate
AND C.CaseId NOT IN (SELECT CaseId FROM CaseStatusChange CSC WHERE CSC.DateClosed < #BeginDate)
--GROUP BY O.OfficeId
UNION
-- Also need the cases that reopened and are currently open
SELECT COUNT(ReOpened.CaseId) As CaseCount, ReOpened.OfficeID
FROM (
SELECT C.CaseId, MAX(CSC.DateReopened) AS DateReOpened, O.OfficeId
FROM [Case] C
INNER JOIN [CaseStatusChange] CSC ON C.CaseId = CSC.CaseId
INNER JOIN [Appointment] A ON C.CaseId = A.CaseId
INNER JOIN [Office] O ON A.OfficeId = O.OfficeId
WHERE CSC.DateReopened <= #BeginDate
--GROUP BY C.CaseId, O.OfficeID
) AS ReOpened
WHERE ReOpened.CaseId NOT IN
(
SELECT CaseId FROM CaseStatusChange
WHERE CaseId = ReOpened.CaseId AND
CaseStatusChange.DateClosed BETWEEN ReOpened.DateReopened AND #BeginDate
)
GROUP BY ReOpened.OfficeId
) AS OpenCasesCount
GROUP BY OfficeId
)
)
CaseOfficeAppointment
INNER JOIN [Case] C ON CaseOfficeAppointment.CaseId = C.CaseId
INNER JOIN [Office] O ON CaseOfficeAppointment.OfficeId = O.OfficeId
INNER JOIN [CaseType] CT ON C.CaseTypeId = CT.CaseTypeId
INNER JOIN [Court] CR ON C.CourtId = CR.CourtId
If I understood you right, you need something like :
CREATE PROCEDURE new_proc
AS
BEGIN
DECLARE #tmp_proc1 TABLE (// list all fields your first procedure returns );
DECLARE #tmp_proc2 TABLE (// list fields that your second SP returns);
INSERT INTO #tmp_proc1
EXECUTE Your_First_Procedure ;
INSERT INTO #tmp_proc2
EXECUTE Your_Second_Procedure;
// Finally, join data in #tmp_proc1 and #tmp_proc2
//(you probably need FULL JOIN) and return 1 resultset
END;
Provided you adjust the header to add all parameters needed, you can add as many result sets to a stored procedure as you need. Consuming the multiple tables will vary based on the language and platform you are using to consume the data, but simply result set from one sproc into the other should work fine, unless there is a limitation in the underlying data store (database server?).
ADDED:
Based on your response, you can combined the two results sets in a single stored procedure. To consume this, you have a variety of options. With a Reader, you can go to next result set, as it is a firehose cursor. But, it might be easier to use something like a DataSet and have it generated form the stored procedure. you can then use a table adapter to fill the data set from the stored procedure. Both tables should be filled now with a single call.
Does this make sense?
Related
I am using azure sql server database. I have written one sql query to generate reprot. Here it is:
;WITH cte AS
(
SELECT ProjectID, CreatedDateUTC, ProductID, LicenseID, BackgroundID from Project p
WHERE CAST(p.CreatedDateUTC AS DATE) >= #StartDate and CAST(p.CreatedDateUTC AS DATE) <= #EndDate
and IsBackgroundUsed = 1
and s7ImageGenerated = 1 and p.SiteCode in ('b2c' )
)
SELECT ProjectID , CreatedDateUTC,
(SELECT BackgroundName from Background b WHERE b.BackgroundID = cte.BackgroundID) AS BackgroundName,
(SELECT Name FROM Product pr WHERE pr.ProductID = cte.ProductID) AS ProductName,
Case WHEN LicenseID is null THEN 'Standard' ELSE (SELECT LicenseName from License l WHERE l.LicenseID = cte.LicenseID) END AS CLA,
(SELECT PurchaseFG from Product_background pb WHERE pb.BackgroundID = cte.BackgroundID and pb.ProductId = cte.productID) AS PurchaseFG,
(SELECT FGcode from Product pr WHERE pr.ProductID = cte.ProductID) AS ProductFGCode,
--(Select dbo.[getProjectFGCodeByBackground](cte.ProductID, cte.BackgroundID)) AS FGCode,
'' AS ERPOrderNumber,
0 AS DesignQuanity
from cte
WHERE (SELECT count(*) from Approval.OrderDetail od WHERE od.ProjectID = cte.ProjectID) = 0
Is there any way to optimize this query. Timeout issue comes. I have written this query in store procedure and calling that store procedure using linq entity framework.
Earlier i have used join but it's more slow down so tried with sub query. Worked more then one year now not working.
This will definitely improve the performance, especially if the table Approval.OrderDetail is large:
...WHERE not exists
(SELECT 1 from Approval.OrderDetail od WHERE od.ProjectID = cte.ProjectID)
Writing a sub-select for every single field is a terrible way to retrieve data, as you'll likely end up with a lot of Loop Joins which have terrible performance over large data sets.
Your original JOIN method is the way to go, but you need to ensure you have appropriate indexes on your joining columns.
You can also replace the WHERE clause, with a LEFT JOIN and IS NULL combination
LEFT JOIN Approval.OrderDetail od
ON od.ProjectID = p.ProjectID
...
AND od.ProjectID IS NULL;
or a NOT EXISTS (although that is more likely to have to SCAN a wider range of rows for each row returned by the main query).
WHERE NOT EXISTS
(SELECT 1 FROM Approval.OrderDetail od WHERE od.ProjectID = cte.ProjectID)
In either case, make sure your Project table is appropriately indexed on (IsBackgroundUsed, s7ImageGenerated, SiteCode, CreatedDate) and that all joins are appropriately indexed.
I'd also question whether you actually need to cast your CreatedDateUTC fields to DATE types?
A possible simplification could be:
SELECT
p.ProjectID,
p.CreatedDateUTC,
b.BackgroundName,
pr.Name,
IIF(p.LicenseID IS NULL, 'Standard', l.LicenseName) AS CLA,
pb.PurchaseFG,
pr.FGCode AS ProductFGCode,
'' AS ERPOrderNumber,
0 AS DesignQuantity
FROM Project p
LEFT JOIN Approval.OrderDetail od
ON od.ProjectID = p.ProjectID
LEFT JOIN Background b
ON b.BackgroundID = p.BackgroundID
LEFT JOIN Product pr
ON pr.ProductID = p.ProductID
LEFT JOIN License l
ON l.LicenseID = p.LicenseID
LEFT JOIN Product_Background pb
ON pb.BackgroundID = p.BackgroundID
AND pb.ProductID = p.ProductID
WHERE p.CreatedDateUTC >= #StartDate AND p.CreatedDateUTC <= #EndDate
AND p.IsBackgroundUsed = 1
AND p.s7ImageGenerated = 1
AND p.SiteCode = 'b2c'
AND od.ProjectID IS NULL;
WHERE CAST(p.CreatedDateUTC AS DATE) >= #StartDate and CAST(p.CreatedDateUTC AS DATE) <= #EndDate
make this SARGAble ,create non clustered index on CreatedDateUTC
Suppose this is the parameter ,
declare #StartDate datetime='2018-02-01'
declare #EndDate datetime='2018-02-28'
Then,
set #EndDate=dateadd(second,-1,dateadd(day,1,#EndDate))
now you can safely use do this,
WHERE p.CreatedDateUTC >= #StartDate and p.CreatedDateUTC <= #EndDate
I think,#Mark Sinkinson query will work ok than sub query.( I will try NOT EXISTS clause once)
Use INNER JOIN if possible.
Hope you are using Store Procedure and calling the SP.
Create index on all joins columns.
Since your sub query is working fine output wise without TOP 1 so it appear that all tables have ONE to ONE relation with Project .
CREATE NONCLUSTERED INDEX IX_Project ON project (
CreatedDateUTC
,IsBackgroundUsed
,s7ImageGenerated
,SiteCode
) include (ProductID,LicenseID,BackgroundID);
Hope projectID is already Clustered Index.
Might not be much faster but easier to read for me.
You should be able to adjust #StartDate and #EndDate and not have to cast to date.
Have an index on all join and where conditions.
If those are FK you should be able to use an inner join (and should).
SELECT P.ProjectID , P.CreatedDateUTC,
b.BackgroundName,
pr.Name AS ProductName,
isnull(l.LicenseName, 'Standard') as CLA,
pb.PurchaseFG,
pr.FGcode AS ProductFGCode,
'' AS ERPOrderNumber,
0 AS DesignQuanity
from Project p
left join Background b
on b.BackgroundID = p.BackgroundID
left join Product pr
on pr.ProductID = p.ProductID
left join License l
on l.LicenseID = p.LicenseID
left join Product_background pb
on pb.BackgroundID = p.BackgroundID
and pb.ProductId = p.productID
left join Product pr
on pr.ProductID = p.ProductID
WHERE CAST(p.CreatedDateUTC AS DATE) >= #StartDate
and CAST(p.CreatedDateUTC AS DATE) <= #EndDate
and p.IsBackgroundUsed = 1
and p.s7ImageGenerated = 1
and p.SiteCode = 'b2c'
and not exists (SELECT 1
from Approval.OrderDetail od
WHERE od.ProjectID = p.ProjectID)
I need help with this. I have this SQL statement:
ALTER proc [dbo].[GetDSR]
(
#WholeSellerId varchar(50),
#FromDate date
)
as
begin
with cte1 as
(select co.ProductId as copid, co.DateAdded as coda, sum(isnull(co.quantity,0)) as coq, co.WholeSellerId as coid
from ConsignmentSale co
group by co.ProductId, co.DateAdded, co.WholeSellerId),
cte2 as
(select ca.ProductId as caid, sum(isnull(ca.quantity,0)) as caq from CashSale ca
group by ca.ProductId),
cte3 as
(select wi.ProductId as wiid, sum(isnull(wi.Quantity,0)) as wiq from Withdrawal wi
group by wi.ProductId),
cte4 as
(select po.ProductId as poid, sum(isnull(po.Quantity,0)) as poq from Pullout po
group by po.ProductId),
cte5 as
(select pr.ProductId as prid, sum(isnull(pr.Quantity,0)) as prq from Promotion pr
group by pr.ProductId)
select cte1.copid as Product, cte1.coda, isnull(cte1.coq,0) as Credit, isnull(cte2.caq,0) as Cash,
isnull(cte3.wiq,0) as Withdrawal, isnull(cte4.poq,0) as Pullout, isnull(cte5.prq,0) as Promotion
from cte1
full outer join cte2 on cte2.caid=cte1.copid
full outer join cte3 on cte3.wiid=cte1.copid
full outer join cte4 on cte4.poid=cte1.copid
full outer join cte5 on cte5.prid=cte1.copid
where cte1.coid = #WholeSellerId and cte1.coda = #FromDate
end
go
It gives me the right result only when there is a data in the ConsignmentSale that meets the specific condition. The problem is, when there is no data in the ConsignmentSale that meets the condition but there is in some other table, it is not displayed. Probably it is because of this part:
where cte1.coid = #WholeSellerId and cte1.coda = #FromDate
It is only using the criteria in a single table, the ConsignmentSale, and it does not check the rest of the table for this criteria. Please show me how to alter this procedure in such a way that even if in the ConsignmentSale the criteria is not met but in the other table it is met, it will still give me result and the coq is just going to be 0 since it does not have data that adheres to that criteria.
Thank you.
Move the filter's to ON condition
................
FROM cte1
FULL OUTER JOIN cte2
ON cte2.caid = cte1.copid
AND cte1.coid = #WholeSellerId
AND cte1.coda = #FromDate
FULL OUTER JOIN cte3
ON cte3.wiid = cte1.copid
FULL OUTER JOIN cte4
ON cte4.poid = cte1.copid
FULL OUTER JOIN cte5
ON cte5.prid = cte1.copid
.................
I just created a criteria on each statement like so:
ALTER proc [dbo].[GetDSR]
(
#WholeSellerId varchar(50),
#FromDate date
)
as
begin
with
cte1 as
(select pr.ProductId from Product pr),
cte2 as
(select co.WholeSellerId as cowi, co.DateAdded as coda, co.ProductId as coid, sum(isnull(co.Quantity,0)) as coq from ConsignmentSale co
where co.WholeSellerId=#WholeSellerId and co.DateAdded=#FromDate
group by co.ProductId, co.DateAdded, co.WholeSellerId),
cte3 as
(select ca.DateAdded as cada, ca.WholeSellerId as cawi, ca.ProductId as caid, sum(isnull(ca.Quantity,0)) as caq from CashSale ca
where ca.WholeSellerId=#WholeSellerId and ca.DateAdded=#FromDate
group by ca.ProductId, ca.WholeSellerId, ca.DateAdded),
cte4 as
(select pm.DateAdded as pmda, pm.ProductId as pmid, pm.WholeSellerId as pmwi, sum(isnull(pm.Quantity,0)) as pmq from Promotion pm
where pm.WholeSellerId=#WholeSellerId and pm.DateAdded=#FromDate
group by pm.DateAdded, pm.ProductId, pm.WholeSellerId),
cte5 as
(select wi.ProductId as wiid, wi.DateAdded as wida, wi.WholeSellerId as wiwi, sum(isnull(wi.Quantity,0)) as wiq from Withdrawal wi
where wi.WholeSellerId=#WholeSellerId and wi.DateAdded=#FromDate
group by wi.DateAdded, wi.WholeSellerId, wi.ProductId),
cte6 as
(select po.ProductId as poid, po.DateAdded as poda, po.WholeSellerId as powi, sum(isnull(po.Quantity,0)) as poq from Pullout po
where po.WholeSellerId=#WholeSellerId and po.DateAdded=#FromDate
group by po.ProductId, po.DateAdded, po.WholeSellerId)
select cte1.ProductId as 'Product', isnull(cte2.coq,0) as 'Credit', isnull(cte3.caq,0) as 'Cash', isnull(cte5.wiq,0) as 'Withdrawal',
isnull(cte6.poq,0) as 'Pullout', isnull(cte4.pmq,0) as 'Promotion'
from cte1
full outer join cte2 on cte2.coid = cte1.ProductId
full outer join cte3 on cte3.caid=cte1.ProductId
full outer join cte4 on cte4.pmid=cte1.ProductId
full outer join cte5 on cte5.wiid=cte1.ProductId
full outer join cte6 on cte6.poid=cte1.ProductId
end
I have created a Crystal Report that uses a stored procedure on my SQL Server to return all cards that make a transaction within a given time-scale.
I intend to only identify if a card has been used, and then return the last row (transaction) that the card has made. This should mean that I only return one row per card, regardless of how many transactions are made.
However, when I create a report my output looks like this:
My stored procedure looks like this:
ALTER PROCEDURE [dbo].[RptCardUseDateRange]
-- Add the parameters for the stored procedure here
#DateStart datetime,
#DateEnd datetime
AS
BEGIN
SELECT
PK_Customer,
dbo.getCustomerFullName(PK_Customer) AS FullName,
CardNumber,
NRTransactions,
SchemeName,
DateOfLastTransaction,
TransactionDate
FROM
[Card] C
INNER JOIN CardStatus CS ON C.FK_CardStatus = CS.PK_CardStatus
LEFT JOIN Customer CU ON C.FK_Customer = CU.PK_Customer
INNER JOIN [User] U ON CU.FK_User = U.PK_User
INNER JOIN [Scheme] S ON CU.FK_Scheme = S.PK_Scheme
INNER JOIN [Transaction] T ON C.PK_Card = T.FK_Card
WHERE
TransactionDate BETWEEN #DateStart AND #DateEnd
ORDER BY PK_Customer desc, CardNumber
END
So SO my question is, what should I add to only return one row per card number?
From other posts I have looked at, I have an idea it is something like:
cross apply(select top 1 PK_Transaction From [Transaction] T where T.FK_Card = C.PK_Card) X
But this does nothing, as I suspect I am putting the wrong parameters in.
You need to find the MAX transaction date for each card and get just those records
WITH Data(PK_Customer,FullName, CardNumber, NRTransactions, SchemeName, TransactionDate)
AS
(
SELECT
PK_Customer,
dbo.getCustomerFullName(PK_Customer) AS FullName,
CardNumber,
NRTransactions,
SchemeName,
DateOfLastTransaction,
TransactionDate
FROM
[Card] C
INNER JOIN CardStatus CS ON C.FK_CardStatus = CS.PK_CardStatus
LEFT JOIN Customer CU ON C.FK_Customer = CU.PK_Customer
INNER JOIN [User] U ON CU.FK_User = U.PK_User
INNER JOIN [Scheme] S ON CU.FK_Scheme = S.PK_Scheme
INNER JOIN [Transaction] T ON C.PK_Card = T.FK_Card
WHERE
TransactionDate BETWEEN #DateStart AND #DateEnd
)
SELECT d.*
FROM DATA d
INNER JOIN (
SELECT CardNumber, MAX(TransactionDate) AS TransactionDate
FROM DATA
GROUP BY CardNumber
) md ON d.CardNumber=md.CardNumber and d.TransactionDate = md.TransactionDate
ORDER BY d.PK_Customer desc, d.CardNumber
Found the Answer.
Looking at this post, it would seem that I was being silly and overcomplicating things.
All I had to change was TransactionDate in SELECT to min(TransactionDate) and then group the rest to create:
Group By PK_Customer, CardNumber, NRTransactions, SchemeName, DateOfLastTransaction
Create PROCEDURE [dbo].[K_RT_FixedAsset]
#fromdate datetime,
#todate datetime
AS
BEGIN
SET NOCOUNT ON;
select convert(varchar,FT.date,103)as date, MR.branch as frombranch,PD.productname as product,FT.vehicleno,FT.dcno,FT.tobranch
from K_RT_FixedAssetTransfer FT
inner join K_RT_MasterRetailStores MR on MR.sno = FT.frombranch
inner join K_RT_ProductDetails PD on PD.sno=FT.product
inner join K_RT_MasterRetailStores MR on MR.sno = FT.tobranch
where FT.date between #fromdate and #todate
END
You must use a different alias for each join of K_RT_MasterRetailStores.
The others are saying to use a different alias, but perhaps it's not clear to you what they mean:
select convert(varchar,FT.date,103)as date, MR_from.branch as frombranch,
PD.productname as product,FT.vehicleno,FT.dcno,FT.tobranch
from K_RT_FixedAssetTransfer FT
inner join K_RT_MasterRetailStores MR_from --<-- First alias
on MR_from.sno = FT.frombranch
inner join K_RT_ProductDetails PD on PD.sno=FT.product
inner join K_RT_MasterRetailStores MR_to --<-- Second alias
on MR_to.sno = FT.tobranch
where FT.date between #fromdate and #todate
I note that you're not using anything from the second join in the SELECT list. Maybe you wanted to use that instead of FT.tobranch?
select convert(varchar,FT.date,103)as date, MR_from.branch as frombranch,
PD.productname as product,FT.vehicleno,FT.dcno,MR_to.branch
from K_RT_FixedAssetTransfer FT
inner join K_RT_MasterRetailStores MR_from on MR_from.sno = FT.frombranch
inner join K_RT_ProductDetails PD on PD.sno=FT.product
inner join K_RT_MasterRetailStores MR_to on MR_to.sno = FT.tobranch
where FT.date between #fromdate and #todate
You've joined K_RT_MasterRetailStores on twice with the same alias.
Depending on whether this join needs to be in twice you either need to
Delete the second join
Use a different alias
--Rename the alias names
inner join K_RT_MasterRetailStores MR1 on MR1.sno = FT.frombranch
inner join K_RT_MasterRetailStores MR2 on MR2.sno = FT.tobranch
here's a quandry I'm facing in SSRS that I'm a bit stumped on. Here's the business logic I'm trying to create.
In determining the correct # of days in lab, use the following the logic:
If a case has multiple detail items with the same BacklogGroup, Daysinlab = Max(DaysinlabGDL)
If the items are from different BackLogGroups Sum the DaysInLabGDL from each of the BackLogGroups to get the DaysInLab amount.
So for example:
Case ID Back Log Group Days Calc Days
In Lab
4595549 EMAX 5 7
4595550 EMAX 5 2
4595551 CLINICAL ZIRC 5 3
4595552 BruxZir H 5 3
4595559 Implant SS 5 4
4595559 IMPLANTCA 8 8
The Expression I'm using for Calc days is this:
=iif(Fields!CaseID.Value = Previous(Fields!CaseID.Value) and Fields!BackLogGroup.Value <> Previous(Fields!BackLogGroup.Value),Fields!ActualDaysInLab.Value + Previous(Fields!ActualDaysInLab.Value),Max(Fields!ActualDaysInLab.Value))
In essence what I'm trying to do is compare detail records within a case and if the backlog group is different for each of the detail records (there can be more than 2 detail recs/case) sum the days in lab column. If the backlog groups are the same for the detail recs then I want to take the max() of the days in lab.
If there is a case where there are say 3 detail recs and two have the same backlog group take the max of those and add them to the other.
So in the case above Calc days for caseID 4595559 should be 13 (5+8) for both detail recs. But for some reason I'm not getting that. I wound up with one being 4 and one being 8.
In case it makes a difference here's the SQL query that creates the dataset:
Declare #StartDate Datetime
Declare #EndDate Datetime
Set #StartDate = '12/01/2013'
Set #EndDate = GetDate()
SELECT
cp.CaseID
,c.DateIn
,c.DateInvoiced
,cp.ProductID
,p.BackLogGroup
,sra.SourceCategory
,sra.DaysInLabGDL
,DATEDIFF(DAY,c.DateIn,c.DateInvoiced) AS ActualDaysInLab
,dbo.GL_GetBusinessDayCount(c.DateIn,c.DateInvoiced) AS WorkingDays
FROM dbo.CaseProducts cp WITH (NOLOCK)
INNER JOIN dbo.Cases c WITH (NOLOCK)
ON cp.CaseID = c.CaseID
LEFT OUTER JOIN dbo.Products p WITH (NOLOCK)
ON cp.ProductID = p.ProductID
LEFT OUTER JOIN dbo.SalesReAllocation sra WITH (NOLOCK)
ON p.ProductID = sra.ProductID
WHERE
p.BackLogGroup IS NOT NULL
AND
c.DateInvoiced IS NOT NULL
AND
c.DateIn between #StartDate and #EndDate
Order by
cp.CaseID
I hope this is clear. If not let me know and I'll try and clarify.
Thanks in advance.
I am calling your first result set t (for convenience).
I think the solution to your problem is a double aggregation:
select CaseId, sum(DaysInLab) as DaysInLab
from (select CaseID, BackLogGroup, max(DaysInLabGDL) as DaysInLab
from t
group by CaseId, BackLogGroup
) blg
group by CaseId;
So here is the Final Query. Thanks for the help #Gordon Linoff. It put me on the right path.
Declare #StartDate Datetime
Declare #EndDate Datetime
Set #StartDate = '12/01/2013'
Set #EndDate = GetDate()
With t as
(
SELECT
--count(cp.caseID) as CaseCount
cp.CaseID
,c.DateIn
,c.DateInvoiced
,cp.ProductID
,p.BackLogGroup
,sra.SourceCategory
,sra.DaysInLabGDL
,DATEDIFF(DAY,c.DateIn,c.DateInvoiced) AS ActualDaysInLab
,dbo.GL_GetBusinessDayCount(c.DateIn,c.DateInvoiced) AS WorkingDays
FROM dbo.CaseProducts cp WITH (NOLOCK)
INNER JOIN dbo.Cases c WITH (NOLOCK)
ON cp.CaseID = c.CaseID
LEFT OUTER JOIN dbo.Products p WITH (NOLOCK)
ON cp.ProductID = p.ProductID
LEFT OUTER JOIN dbo.SalesReAllocation sra WITH (NOLOCK)
ON p.ProductID = sra.ProductID
WHERE
p.BackLogGroup IS NOT NULL
AND
c.DateInvoiced IS NOT NULL
AND
--cp.CaseID = 4595187
c.DateIn between #StartDate and #EndDate
)
select blg.CaseID, DateIn, DateInvoiced, sum(DaysInLab) as DaysInLab, blg2.BackLogGroup, blg2.Workingdays, blg2.Workingdays - sum(Daysinlab) as DaysOver
from (select CaseID, BackLogGroup, max(DaysInLabGDL) as DaysInLab, WorkingDays
from t
group by CaseId, BackLogGroup, WorkingDays
) blg
Inner Join (Select CaseID, DateIn, DateInvoiced, BackLogGroup, WorkingDays
from t
group by CaseID, DateIn, DateInvoiced, BackLogGroup, WorkingDays
) blg2 on blg.CaseID = blg2.CaseId
group by blg.CaseId, DateIn, DateInvoiced, blg2.BackLogGroup, blg2.Workingdays
having blg2.workingdays > sum(Daysinlab)