I am running the below query which is failing when it fills up the tempdb (170GB). It fails after around 1 hour.
the script below :
--Select Query BOM collection retail report
Declare #Company Nvarchar(50) ='HMFI'
Declare #Product Nvarchar(50) =Null
select Upper (Be.DataAreaId)Company ,BE.BOM,BE.Product
,Max(ProItemName)ProItemName
,Max(ProUnitID)ProUnitID
,Be.Material,Max(MaterialItemName)MaterialItemName
,Be.UNITID MaterialUnitID
,Sum (Be.BOMQTY)MaterialQty
,Max (MaterialService) MaterialType
from ExpBom_HMFI BE
Outer Apply (SELECT UNITID ProUnitID FROM INVENTTABLEMODULE A With (Nolock) WHERE DATAAREAID = #Company AND A.ITEMID =BE.Product AND MODULETYPE = 0)ProUnitID
Outer Apply(SELECT ITEMNAME ProItemName FROM INVENTTABLE B With (Nolock) WHERE DATAAREAID = #Company AND B.ITEMID = BE.Product)ProItemName
Outer Apply(SELECT ITEMNAME MaterialItemName FROM INVENTTABLE C With (Nolock) WHERE DATAAREAID = #Company AND C.ITEMID = Be.Material)MaterialItemName
Outer Apply(SELECT Case When ITEMTYPE=0 Then 'Item' When ITEMTYPE=1 Then 'BOM' When ITEMTYPE=2 Then 'Service Item' End MaterialService
FROM INVENTTABLE With (Nolock) WHERE DATAAREAID = #Company AND ITEMID = Be.Material)MaterialService
Where BE.DataAreaId in (#Company) and (#Product Is null Or Be.Product In(Select StringValue From Split(#Product,',')))
Group by Be.DataAreaId,BE.BOM,BE.Product,Be.Material ,Be.UNITID
Order By Be.DataAreaId,BE.BOM,BE.Product,Be.Material
option (maxrecursion 0)
--now Viewing the data collected
with ExpBom (
DataAreaId,
Bom,
Product,
Material,
BomDepth,
BOMQTY,
Unitid,
BomPath
) as (
select
bv.DataAreaId,
bv.BomId,
bv.ItemId,
b.ItemId,
1,
Convert (NUMERIC(18,8), b.BOMQTY) BOMQTY,
Convert (Nvarchar(10),b.UNITID )Unitid,
convert(Nvarchar(max), bv.ItemId + '|' + b.ItemId) as BomPath
from BomVersion bv With (Nolock)
join InventTable ibv With (Nolock)
on ibv.DataAreaId = bv.DataAreaId
and ibv.ItemId = bv.ItemId
join Bom b With (Nolock)
on b.DataAreaId = bv.DataAreaId
and b.BomId = bv.BomId
join InventTable ib With (Nolock)
on ib.DataAreaId = b.DataAreaId
and ib.ItemId = b.ItemId
where bv.Approved = 1
and bv.Active = 1
and bv.FromDate < getdate()
and (bv.ToDate = '01-01-1900' or bv.ToDate >= getdate())
and b.FromDate < getdate()
and (b.ToDate = '01-01-1900' or b.ToDate >= getdate())
and b.DATAAREAID in ('HMFI')
union all
select
bv.DataAreaId,
bv.BomId,
bv.ItemId,
eb.Material,
eb.BomDepth + 1,
Convert (NUMERIC(18,8),B.BOMQTY * eb.BOMQTY)BOMQTY,
Convert (Nvarchar(10),eb.UNITID )Unitid,
convert(Nvarchar(max), bv.ItemId + '|' + eb.BomPath) as BomPath
from BomVersion bv With (Nolock)
join InventTable ibv With (Nolock)
on ibv.DataAreaId = bv.DataAreaId
and ibv.ItemId = bv.ItemId
join Bom b With (Nolock)
on b.DataAreaId = bv.DataAreaId
and b.BomId = bv.BomId
join ExpBom eb
on eb.DataAreaId = b.DataAreaId
and eb.Product = b.ItemId
where bv.Approved = 1
and bv.Active = 1
and bv.FromDate < getdate()
and (bv.ToDate = '01-01-1900' or bv.ToDate >= getdate())
and b.FromDate < getdate()
and (b.ToDate = '01-01-1900' or b.ToDate >= getdate())
and b.DATAAREAID in ('HMFI')
)
select * from ExpBOM
Where Material Not in (Select BOMV.ITEMID From BomVersion BOMV With (Nolock) Where BOMV.DataAreaId In( 'HMFI' ) and BOMV.Approved = 1
and BOMV.Active = 1
and BOMV.FromDate < getdate()
and (BOMV.ToDate = '01-01-1900' or BOMV.ToDate >= getdate()) )
I'm not sure if the JOINS are causing the issue
Estimated execution plan is below:
Data collection :
https://www.brentozar.com/pastetheplan/?id=S1UsXn4Po
Data view:
https://www.brentozar.com/pastetheplan/?id=BJDUBn4wi
Please advise
this report was working fine on daily basis without filling tempdb usualy it was taking 1 min to execute suddenly it stoped for unknown reason although there's no changes done on server/database levels
I have the following SQL query statement:
INSERT INTO #mt_API
SELECT
[dbo].fn_AddTimeZoneOffset(APHIST.ActionDate,'CET') AS ASDATE
, [dbo].fn_AddTimeZoneOffset(APHIST.ReturnDate,'CET') AS ATDATE
,API_HIST.[ActionPlanItemID]
,API_HIST.[ActionPlanID]
,PIT.[ProductItemID]
,PIT.ProductItemCode
,PIT.QRCode
,PIT.Name
,ISNULL((SELECT TOP 1 mRSP.TotalRemainingAtStore FROM #mt_RemainingStockProduct AS mRSP
WHERE mRSP.InventoryDate <= APHIST.ReturnDate
ORDER BY mRSP.InventoryDate DESC), 0) AS StoreTotalStock
,P.[Weight] AS ItemWeight
,M.UnitMeasureCode as Unit
,PIT.Quantity AS ItemQuantity
,P.ItemUnitWeight
,P.Quantity as ProductQuantity
,E1.FullName AS Emp1
,E2.FullName AS Emp2
,E3.FullName AS Emp3
,E4.FullName AS Emp4
,SECT.Name AS Sector
,CASE WHEN n=0 then 0 else [ItemStatus] end as [ItemStatus]
,APHIST.IsActionOver as ActionOver
FROM
[Sales].[ActionPlanItem_History] AS API_HIST
INNER JOIN
[Sales].[ActionPlan_History] AS APHIST On APHIST.ActionPlanID = API_HIST.ActionPlanID
INNER JOIN
[Production].[ProductItem] AS PIT ON API_HIST.ProductItemID =PIT.ProductItemID
INNER JOIN
Production.Product as P ON PIT.ProductID = P.ProductID AND PIT.ProductID = P.ProductID AND
PIT.ProductID = P.ProductID
INNER JOIN
Production.UnitMeasure as M ON M.UnitMeasureID = P.WeightUnitMeasureID
LEFT OUTER JOIN
Sales.Employee AS E1 ON APHIST.EmployeeID1 = E1.EmployeeID
LEFT OUTER JOIN
Sales.Employee AS E2 ON APHIST.EmployeeID2 = E2.EmployeeID
LEFT OUTER JOIN
Sales.Employee AS E3 ON APHIST.EmployeeID3 = E3.EmployeeID
LEFT OUTER JOIN
Sales.Employee AS E4 ON APHIST.EmployeeID4 = E4.EmployeeID
INNER JOIN
Sales.Sector AS SECT ON APHIST.SectorID = SECT.SectorID
INNER JOIN
Production.ProductSubcategory as PS on P.ProductSubcategoryID=PS.ProductSubcategoryID
INNER JOIN
Production.ProductCategory as PC on PS.ProductCategoryID= PC.ProductCategoryID
CROSS APPLY (Values(0),(1)) d(n)
WHERE P.StoreID=#StoreID
--WHERE PC.ProductCategoryID=#RootCategory AND P.StoreID=#StoreID
--ORDER BY ProductItemCode, ATDATE
ORDER BY ASDATE , ProductItemCode
SELECT
API1.ASDATE AS StartDate
,API1.ATDATE AS ReturnDate
,API1.ActionPlanItemID
,API1.ActionPlanID
,API1.ProductItemID
,API1.ProductItemCode
,API1.QRCode
,API1.Name
,API1.StoreTotalStock
,API1.ItemWeight
,API1.ItemQuantity
,API1.ItemUnitWeight
,API1.Unit
,API1.ProductQuantity
,API1.Emp1
,API1.Emp2
,API1.Emp3
,API1.Emp4
,API1.Sector
,API1.ItemStatus
,API1.ActionOver
,(API1.StoreTotalStock +
(SELECT SUM(
CASE API2.ItemStatus
WHEN 0 THEN -1
WHEN 1 THEN 1
ELSE 0
END * API2.ItemUnitWeight)
FROM #mt_API AS API2
WHERE API2.ID <= API1.ID
)
-
(
**select
case ISNULL(SUM([ProductItemWeight]), 0)
when 0 then 0
else SUM([ProductItemWeight])
end
from [ExplosiveTracking].[Production].[TransfertHistory]
where stuff(convert(varchar(20),TransfertDateTime,120),17,6,'') < stuff(convert(varchar(20),API1.ASDATE,120),17,6,'')**
)
) AS ItemWeightBal
FROM #mt_API AS API1
Inside the CASE statement I am returning the SUM([ProductItemWeight]) if it is not NULL, but then at same time, I need to execute the following inside the same CASE :
delete from #tempTransfert
where stuff(convert(varchar(20),#tempTransfert.TransferDate,120),17,6,'') < stuff(convert(varchar(20),API1.ASDATE,120),17,6,'')
ADDED MORE TEST :
If I run what I wan to accomplish in a standalone new query as below then the DELETE and SELECT works find inside the CASE
CREATE TABLE #tempTransfert
(
[ID] uniqueidentifier,
[ProductId] int,
[SourceId] int,
TransferDate DateTime,
TotalMovedProduct DECIMAL(16,4)
)
Insert into #tempTransfert
select
[ID],[ProductId], [SourceId], stuff(convert(varchar(20),TransfertDateTime,120),17,6,'') as TransferDate, SUM([ProductItemWeight]) as TotalMovedProduct
from [ExplosiveTracking].[Production].[TransfertHistory]
group by [ProductId],ID, [SourceId], stuff(convert(varchar(20),TransfertDateTime,120),17,6,'')
select * from #tempTransfert
MERGE #tempTransfert AS T
USING (select
case ISNULL(SUM([ProductItemWeight]) , 0)
when 0 then 0
else SUM([ProductItemWeight])
end
, ID
from [ExplosiveTracking].[Production].[TransfertHistory]
where stuff(convert(varchar(20),TransfertDateTime,120),17,6,'') < stuff(convert(varchar(20),'2017-02-28 15:38:00',120),17,6,'')
Group by ID
) as S ([ProductItemWeight],ID)
ON (T.ID = S.ID)
WHEN MATCHED
THEN DELETE;
BUT when I added in the complete query as below , I have a SYNTAX error near MERGE reported :
DECLARE #m_StoreTotalStock AS DECIMAL(18,3)
DECLARE #mt_API AS TABLE
(
ID INT IDENTITY(1,1), ASDATE DATETIME,ATDATE DATETIME,
ActionPlanItemID INT, ActionPlanID INT,
ProductItemID INT, ProductItemCode VARCHAR(50),
QRCode VARCHAR(50), Name VARCHAR(50),
StoreTotalStock decimal(18,3), ItemWeight decimal(18,3),
Unit VARCHAR(50), ItemQuantity INT,
ItemUnitWeight DECIMAL(18,4), ProductQuantity INT,
Emp1 VARCHAR(50), Emp2 VARCHAR(50),
Emp3 VARCHAR(50), Emp4 VARCHAR(50),
Sector VARCHAR(50), ItemStatus TINYINT,ActionOver INt
)
DECLARE #mt_RemainingStockProduct AS TABLE
(
StoreID INT,InventoryDate DATETIME,ProductID INT, TotalRemainingAtStore DECIMAL(18,2)
)
CREATE TABLE #tempTransfert
(
[ID] uniqueidentifier,
[ProductId] int,
[SourceId] int,
TransferDate DateTime,
TotalMovedProduct DECIMAL(16,4)
)
Insert into #tempTransfert
select
[ID],[ProductId], [SourceId], stuff(convert(varchar(20),TransfertDateTime,120),17,6,'') as TransferDate, SUM([ProductItemWeight]) as TotalMovedProduct
from [ExplosiveTracking].[Production].[TransfertHistory]
group by [ProductId],ID, [SourceId], stuff(convert(varchar(20),TransfertDateTime,120),17,6,'')
select * from #tempTransfert
/** Get Remaining StockBy Product **/
INSERT INTO #mt_RemainingStockProduct
(
StoreID, InventoryDate, ProductID,TotalRemainingAtStore
)
--SELECT InventoryDate, SUM(TotalRemainingAtStore) AS TotalRemainingAtStore FROM
--(
SELECT StoreID, InventoryDate, ProductID, SUM(Remaining) OVER (PARTITION BY StoreID ) AS TotalRemainingAtStore FROM
(
SELECT
P.StoreID, P.InventoryDate, P.ProductID,
--SUM(PIT.Quantity * P.ItemUnitWeight)-SUM(PIT.UsedQuantity * P.ItemUnitWeight) AS Remaining
SUM(PIT.Quantity * P.ItemUnitWeight) AS Remaining
FROM Sales.Store AS S
INNER JOIN Production.ProductItem AS PIT
INNER JOIN Production.Product AS P ON PIT.ProductID = P.ProductID
INNER JOIN Production.UnitMeasure AS UM ON P.WeightUnitMeasureID = UM.UnitMeasureID ON
S.BusinessEntityID = P.StoreID
INNER JOIN Production.Location AS LOC ON S.BusinessEntityID = LOC.StoreID AND
P.LocationID = LOC.LocationID AND P.LocationID = LOC.LocationID
WHERE (P.IsDeleted = 0) AND (PIT.IsDeleted = 0) AND P.StoreID = 4
GROUP BY P.StoreID,P.InventoryDate, P.ProductID, UM.UnitMeasureCode, S.Name, LOC.MaxQuantity
) AS RST1
--) AS RST2
--GROUP BY RST2.InventoryDate
/** Endof Get Remaining StockBy Product **/
-- Get Store total product items weight
SELECT #m_StoreTotalStock = SUM(PIW.TotalWeight)
FROM dbo.v_ProductItemWeight AS PIW
WHERE StoreID = 4
INSERT INTO #mt_API
SELECT [dbo].fn_AddTimeZoneOffset(APHIST.ActionDate,'CET') AS ASDATE
, [dbo].fn_AddTimeZoneOffset(APHIST.ReturnDate,'CET') AS ATDATE
,API_HIST.[ActionPlanItemID]
,API_HIST.[ActionPlanID]
,PIT.[ProductItemID]
,PIT.ProductItemCode
,PIT.QRCode
,PIT.Name
,ISNULL((SELECT TOP 1 mRSP.TotalRemainingAtStore FROM #mt_RemainingStockProduct AS mRSP
WHERE mRSP.InventoryDate <= APHIST.ReturnDate
ORDER BY mRSP.InventoryDate DESC), 0) AS StoreTotalStock
,P.[Weight] AS ItemWeight
,M.UnitMeasureCode as Unit
,PIT.Quantity AS ItemQuantity
,P.ItemUnitWeight
,P.Quantity as ProductQuantity
,E1.FullName AS Emp1
,E2.FullName AS Emp2
,E3.FullName AS Emp3
,E4.FullName AS Emp4
,SECT.Name AS Sector
,CASE WHEN n=0 then 0 else [ItemStatus] end as [ItemStatus]
,APHIST.IsActionOver as ActionOver
FROM
[Sales].[ActionPlanItem_History] AS API_HIST
INNER JOIN
[Sales].[ActionPlan_History] AS APHIST On APHIST.ActionPlanID = API_HIST.ActionPlanID
INNER JOIN
[Production].[ProductItem] AS PIT ON API_HIST.ProductItemID =PIT.ProductItemID
INNER JOIN
Production.Product as P ON PIT.ProductID = P.ProductID AND PIT.ProductID = P.ProductID AND
PIT.ProductID = P.ProductID
INNER JOIN
Production.UnitMeasure as M ON M.UnitMeasureID = P.WeightUnitMeasureID
LEFT OUTER JOIN
Sales.Employee AS E1 ON APHIST.EmployeeID1 = E1.EmployeeID
LEFT OUTER JOIN
Sales.Employee AS E2 ON APHIST.EmployeeID2 = E2.EmployeeID
LEFT OUTER JOIN
Sales.Employee AS E3 ON APHIST.EmployeeID3 = E3.EmployeeID
LEFT OUTER JOIN
Sales.Employee AS E4 ON APHIST.EmployeeID4 = E4.EmployeeID
INNER JOIN
Sales.Sector AS SECT ON APHIST.SectorID = SECT.SectorID
INNER JOIN
Production.ProductSubcategory as PS on P.ProductSubcategoryID=PS.ProductSubcategoryID
INNER JOIN
Production.ProductCategory as PC on PS.ProductCategoryID= PC.ProductCategoryID
CROSS APPLY (Values(0),(1)) d(n)
WHERE P.StoreID=4
--WHERE PC.ProductCategoryID=#RootCategory AND P.StoreID=#StoreID
--ORDER BY ProductItemCode, ATDATE
ORDER BY ASDATE , ProductItemCode
SELECT
API1.ASDATE AS StartDate
,API1.ATDATE AS ReturnDate
,API1.ActionPlanItemID
,API1.ActionPlanID
,API1.ProductItemID
,API1.ProductItemCode
,API1.QRCode
,API1.Name
,API1.StoreTotalStock
,API1.ItemWeight
,API1.ItemQuantity
,API1.ItemUnitWeight
,API1.Unit
,API1.ProductQuantity
,API1.Emp1
,API1.Emp2
,API1.Emp3
,API1.Emp4
,API1.Sector
,API1.ItemStatus
,API1.ActionOver
,(API1.StoreTotalStock +
(SELECT SUM(
CASE API2.ItemStatus
WHEN 0 THEN -1
WHEN 1 THEN 1
ELSE 0
END * API2.ItemUnitWeight)
FROM #mt_API AS API2
WHERE API2.ID <= API1.ID
)
-
--select
-- case ISNULL(SUM([ProductItemWeight]), 0)
-- when 0 then 0
-- else SUM([ProductItemWeight])
-- end
--from [ExplosiveTracking].[Production].[TransfertHistory]
--where stuff(convert(varchar(20),TransfertDateTime,120),17,6,'') < stuff(convert(varchar(20),API1.ASDATE,120),17,6,'')
(
**MERGE #tempTransfert AS T
USING (select
case ISNULL(SUM([ProductItemWeight]) , 0)
when 0 then 0
else SUM([ProductItemWeight])
end
, ID
from [ExplosiveTracking].[Production].[TransfertHistory]
where stuff(convert(varchar(20),TransfertDateTime,120),17,6,'') < stuff(convert(varchar(20),API1.ASDATE,120),17,6,'')
Group by ID
) as S ([ProductItemWeight],ID)
ON (T.ID = S.ID)
WHEN MATCHED
THEN DELETE;
)**
) AS ItemWeightBal
FROM #mt_API AS API1
END
The MERGE part is suppose to first return the SUM of ItemWeight within a DateTime range, then when those records has been read, I need to delete them from #tempTransfert table otherwise, on the next loop it will read all records again
Any idea what syntax error can it be ?
Thanks for your help on this
Regards
I have a below procedure which uses 3 temp tables and finally insert into a table. I am using below sp as source (execute sql task) and loading into csv files. When i run this sp from SSMS it runs within 10 seconds, but when I Put into SSIS package it runs for 30 mins and keep on running. Could any of you optimize this SP for SSIS package?
create proc [etl].[payment_report]
#start_date datetime,
#end_date datetime
as
begin
truncate table extract.payment
select
a.bb_acct_id, a.customer_id,
pay.order_id Payment_Order_Id,
aoi.ord_prod_id Ord_Prod_Id,
pd.name, pd.quick_cd
into
#IntialOrders
from
(select *
from stg.payment (NOLOCK)
where order_id is not null) pay
inner join
stg.account a (NOLOCK) on pay.acct_id = a.acct_id
inner join
stg.acct_order ao (NOLOCK) on ao.order_id = pay.order_id
inner join
stg.acct_order_item aoi (NOLOCK) on aoi.order_id = ao.order_id
inner join
stg.ordered_product op (NOLOCK) on op.ord_prod_id = aoi.ord_prod_id
left join
stg.product p (NOLOCK) on p.prod_id = op.prod_id
left join
stg.product_def pd (NOLOCK) on pd.prod_def_id = p.prod_def_id
where
pay.received_date >= #start_date
and pay.received_date < #end_date
and pay.payment_id not in (select payment_id
from stg.op_renewal_history)
create clustered index Idx_Payment_Order_Id on #IntialOrders(Payment_Order_Id)
select
pay.payment_id, gwr.response
into
#gateway_response
from
stg.payment pay (NOLOCK)
inner join
stg.cc_transactions cct (NOLOCK) on cct.payment_id = pay.payment_id
inner join
stg.gateway_response gwr (NOLOCK) on cct.c_c_trans_id = gwr.cc_trans_id
where
pay.posting_status_id = 3
and pay.received_date >= #start_date
and pay.received_date < #end_date
and pay.received_date > '2015-04-15 00:00:00'
select
distinct a.bb_acct_id SP_ACCOUNT_ID
,a.customer_id CP_CUSTOMER_ID
,bu.description BUSINESS_UNIT
,pay.payment_id PAYMENT_ID
,pay.payment_amt AMOUNT
,'SEK' CURRENCY
,Substring(convert(char(19),pay.received_date,126), 1, (len(convert(char(19),pay.received_date,126))-0))+'Z' PAYMENT_DATE
,pt.display_name PAYMENT_METHOD
,post.description PAYMENT_STATUS
,pay.retries PAYMENT_RETRIES
,case when (pay.for_bill_id is not null or orh.op_id is not null) then 'Renewal' else 'OneTime' end as PAYMENT_TYPE
,case when pay.posting_status_id =3 then gwr.response else '' end as FAILURE_REASON
,case when op.ord_prod_id is null then ino.name else pd.name end SUBSCRIPTION_NAME
,case when op.ord_prod_id is null then ino.quick_cd else pd.quick_cd end SKU
,case when op.ord_prod_id is null then ino.Ord_Prod_Id else op.ord_prod_id end ORD_PROD_ID
,convert(char(19),GETDATE(),126)+'Z' EXPORT_TIME
,case when (pay.posting_status_id =3 and pay.retries = 3 ) then 'T' else 'F' end FAILED_EXTENDED_RETRY
into #payment
from stg.payment pay (NOLOCK)
left join #IntialOrders ino (NOLOCK) on
ino.Payment_Order_Id=pay.order_id
left join stg.account a (NOLOCK) on
a.acct_id = pay.acct_id
left join stg.business_unit bu (NOLOCK) on
a.bu_id=bu.bu_id
left join stg.payment_method pm (NOLOCK) on
pm.pay_method_id=pay.payment_method_id
left join stg.payment_type pt (NOLOCK) on
pt.id=pm.type_id
left join stg.posting_status post (NOLOCK) on
post.id=pay.posting_status_id
left join stg.op_renewal_history orh (NOLOCK) on
orh.payment_id = pay.payment_id
left join stg.ordered_product op (NOLOCK) on
op.ord_prod_id = orh.op_id
left join stg.product p (NOLOCK) on
p.prod_id = op.prod_id
left join stg.product_def pd (NOLOCK) on
pd.prod_def_id = p.prod_def_id
left join #gateway_reponse gwr (NOLOCK) on
gwr.payment_id = pay.payment_id
where
a.bu_id=1
and (a.acct_role_id is null or a.acct_role_id !=4)
and (pay.posting_status_id=2 or (pay.posting_status_id =3
and pay.retries = 3
and op.acct_status_id=3))
and pay.received_date >=#start_date
and pay.received_date < #end_date
and pay.received_date > '2015-04-15 00:00:00'
insert into extract.payment
(
SP_ACCOUNT_ID
,CP_CUSTOMER_ID
,BUSINESS_UNIT
,PAYMENT_ID
,AMOUNT
,CURRENCY
,PAYMENT_DATE
,PAYMENT_METHOD
,PAYMENT_STATUS
,PAYMENT_RETRIES
,PAYMENT_TYPE
,FAILURE_REASON
,SUBSCRIPTION_NAME
,SKU,ORD_PROD_ID
,EXPORT_TIME
,FAILED_EXTENDED_RETRY
)
select
cast(p.SP_ACCOUNT_ID as varchar(50)) SP_ACCOUNT_ID
,cast(p.CP_CUSTOMER_ID as varchar(50)) CP_CUSTOMER_ID
,cast(p.BUSINESS_UNIT as varchar(500)) BUSINESS_UNIT
,cast( p.PAYMENT_ID as varchar(50)) PAYMENT_ID, p.AMOUNT
,cast( p.CURRENCY as varchar(50)) CURRENCY
,cast( p.PAYMENT_DATE as varchar(50)) PAYMENT_DATE
,cast( p.PAYMENT_METHOD as varchar(50)) PAYMENT_METHOD
,cast(p.PAYMENT_STATUS as varchar(50)) PAYMENT_STATUS
,cast( p.PAYMENT_RETRIES as varchar(50)) PAYMENT_RETRIES
,cast(p.PAYMENT_TYPE as varchar(50)) PAYMENT_TYPE
,cast( p.FAILURE_REASON as varchar(4000)) FAILURE_REASON
,cast(p.SUBSCRIPTION_NAME as varchar(500)) SUBSCRIPTION_NAME
,cast(p.SKU as varchar(50)) SKU
,cast(p.ORD_PROD_ID as varchar(50)) ORD_PROD_ID
,cast( p.EXPORT_TIME as varchar(50)) EXPORT_TIME
,p.FAILED_EXTENDED_RETRY
from #payment p
order by p.PAYMENT_DATE
Drop table #IntialOrders
Drop table #gateway_reponse
Drop table #payment
END
I've got a web based report pulling out a load of information from our SQL server and wanted to know the best way of adding a "totals" row to the bottom. The query is full of subqueries, so I'm not sure of the best way of adding a summary row on the bottom.
I know the "best" way would be to do this in the presentation layer, but I've got sweet FA knowledge of the presentation layer (as the chap that made it has since left and no-one has the same skill set...!)
SELECT
dbo.Groups.GroupName, dbo.UserGroups.GroupId, dbo.Users.UserName + ' ' + dbo.Users.Surname AS Consultant,
dbo.UserGroups.UserId,
(SELECT COUNT(*) AS ManagerCount
FROM dbo.ClientContacts
WHERE (CreatedUserId = dbo.Users.UserId) AND (CreatedOn BETWEEN #startDate AND #endDate)) AS ManagersAdded,
(SELECT COUNT(*) AS InterviewCount
FROM dbo.Interviews
WHERE (CreatedUserId = dbo.Users.UserId) AND (InterviewTypeId = 1) AND (Createdon BETWEEN #startDate AND #endDate)) AS FirstInterviewCount,
(SELECT COUNT(*) AS InterviewCount
FROM dbo.Interviews AS Interviews_1
WHERE (CreatedUserId = dbo.Users.UserId) AND (InterviewTypeId in (1,3,4)) AND (Createdon BETWEEN #startDate AND #endDate)) AS InterviewCount,
(SELECT COUNT(*) AS InterviewCount
FROM dbo.Interviews AS Interviews_1
WHERE (CreatedUserId = dbo.Users.UserId) AND (InterviewTypeId in (2)) AND (Createdon BETWEEN #startDate AND #endDate)) AS TelephoneCount,
(SELECT COUNT(*) AS DMSpokenTo
FROM dbo.NotebookItems
WHERE (CreatedUserId = dbo.Users.UserId) AND (NotebookTypeId = 56) AND (CreatedOn BETWEEN #startDate AND #endDate)) AS DMSpokenTo,
(SELECT COUNT(*) AS Appspokento
FROM dbo.NotebookItems
WHERE (CreatedUserId = dbo.Users.UserId) AND (NotebookTypeId = 85) AND (CreatedOn BETWEEN #startDate AND #endDate)) AS AppSpokenTo,
(SELECT COUNT(*) AS Marketed
FROM dbo.NotebookItems AS NotebookItems_1
WHERE (CreatedUserId = dbo.Users.UserId) AND (NotebookTypeId = 124) AND (CreatedOn BETWEEN #startDate AND #endDate)) AS Marketed,
(SELECT COUNT(*) AS CVSent
FROM dbo.ApplicantActions
WHERE (CreatedUserId = dbo.Users.UserId) AND (StatusId <> 28) AND (JobId IS NOT NULL) AND (CreatedOn BETWEEN #startDate AND #endDate)) AS CVSent,
(SELECT COUNT(*) AS CVSent
FROM dbo.ApplicantActions
WHERE (CreatedUserId = dbo.Users.UserId) AND (CreatedOn BETWEEN #startDate AND #endDate)) AS Speccv,
(SELECT COUNT(*) AS Meetings
FROM dbo.DiaryEvents
WHERE (CreatedUserId = dbo.Users.UserId) AND (EventTypeID = 29) AND (CreatedOn BETWEEN #startDate AND #endDate)) AS Meetings,
(SELECT COUNT(*) AS VacanciesAdded
FROM dbo.Jobs
WHERE (CreatedUserId = dbo.Users.UserId) AND (CreatedOn BETWEEN #startDate AND #endDate)) AS VacanciesAdded,
(SELECT SUM(pc.CommissionPerc / 100) AS PermPlacements
FROM dbo.Placements
INNER JOIN PlacementConsultants pc on placements.PlacementID = pc.PlacementId
INNER JOIN PlacementSectorDefinedColumns psdc on psdc.PlacementId = placements.PlacementID
WHERE (isnull(psdc.notnewbusiness,'N') = 'N') AND (pc.UserId = dbo.Users.UserId) AND (placements.CreatedOn BETWEEN #startDate AND #endDate) AND (PlacementTypeId <> 6)) AS [Perm Placements],
(SELECT SUM(PlacementFee / 100 * pc.CommissionPerc) AS PermFee
FROM dbo.Placements
INNER JOIN PlacementConsultants pc on placements.PlacementID = pc.PlacementId
INNER JOIN PlacementSectorDefinedColumns psdc on psdc.PlacementId = placements.PlacementID
WHERE (isnull(psdc.notnewbusiness,'N') = 'N') AND (pc.UserId = dbo.Users.UserId) AND (placements.CreatedOn BETWEEN #startDate AND #endDate) AND (PlacementTypeId <> 6)) AS [Perm Fee],
(SELECT SUM(pc.CommissionPerc / 100) AS ContractPlacements
FROM dbo.Placements
INNER JOIN PlacementConsultants pc on placements.PlacementID = pc.PlacementId
INNER JOIN PlacementSectorDefinedColumns psdc on psdc.PlacementId = placements.PlacementID
WHERE (isnull(psdc.notnewbusiness,'N') = 'N') AND (pc.UserId = dbo.Users.UserId) AND (placements.CreatedOn BETWEEN #startDate AND #endDate) AND (PlacementTypeId = 6)) AS [Contract Placements],
(SELECT SUM(dbo.CONTRACT_NETT_VALUE_FOR_INITIAL_PLACEMENT(Placements_1.PlacementID) / 100 * pc.CommissionPerc) AS ContractFee
FROM dbo.Placements AS Placements_1
INNER JOIN PlacementConsultants pc on Placements_1.PlacementID = pc.PlacementId
INNER JOIN PlacementSectorDefinedColumns psdc on psdc.PlacementId = Placements_1.PlacementID
WHERE (isnull(psdc.notnewbusiness,'N') = 'N') AND (pc.UserId = dbo.Users.UserId) AND (Placements_1.CreatedOn BETWEEN #startDate AND #endDate) AND (PlacementTypeId = 6)) AS [Contract Value]
FROM dbo.Groups INNER JOIN
dbo.UserGroups ON dbo.Groups.GroupId = dbo.UserGroups.GroupId INNER JOIN
dbo.Users ON dbo.UserGroups.UserId = dbo.Users.UserId
WHERE (
(dbo.Users.Inactive = 'N') AND (dbo.UserGroups.GroupId = #GroupId) )
and users.userid not in (select userid from UserGroups where GroupId = 57)
One approach could be to do a UNION and then add in another set of subqueries, but that's going to get really messy and ridiculously long winded surely?
Is there a better way of doing it than that?
Try ROLLUP.
For performance reasons, I would consider using table variables or temp tables to avoid multiple queries of the same tables. Also, table variables and temp tables can have at least a primary key, whereas common table expressions are not indexed.
For example:
DECLARE #GroupName VARCHAR(100)
SELECT #GroupName = g.GroupName
FROM dbo.Groups g
WHERE g.GroupId = #GroupId
DECLARE #Users TABLE
(
UserId INT NOT NULL PRIMARY KEY,
Consultant VARCHAR(100) NOT NULL
)
INSERT #Users (UserId, Consultant)
SELECT u.UserId, u.UserName + ' ' + u.Surname
FROM dbo.Users u
INNER JOIN dbo.UserGroups ug ON u.UserId = ug.UserId AND ug.GroupId = #GroupId
WHERE u.Inactive = 'N'
AND NOT EXISTS (SELECT 1 FROM dbo.UserGroups ne
WHERE u.UserId = ne.UserId
AND ne.GroupId = 57)
DECLARE #ClientContacts TABLE
(
UserId INT NOT NULL PRIMARY KEY,
ManagerCount INT NOT NULL
)
INSERT #ClientContacts (UserId, ManagerCount)
SELECT u.UserId, COUNT(*)
FROM #Users u
INNER JOIN dbo.ClientContacts cc ON cc.CreatedUserId = u.UserId AND cc.CreatedOn BETWEEN #startDate AND #endDate
GROUP BY u.UserId
DECLARE #Interviews TABLE
(
UserId INT NOT NULL,
InterviewTypeId INT NOT NULL,
InterviewCount INT NOT NULL,
PRIMARY KEY (UserId, InterviewTypeId)
)
INSERT #Interviews (UserId, InterviewTypeId, InterviewCount)
SELECT u.UserId, i.InterviewTypeId, COUNT(*)
FROM #Users u
INNER JOIN dbo.Interviews i ON u.UserId = i.CreatedUserId AND i.InterviewTypeId BETWEEN 1 AND 4 AND i.CreatedOn BETWEEN #StartDate AND #EndDate
GROUP BY u.UserId, i.InterviewTypeId
-- Rest is an exercise for the reader, but:
SELECT #GroupName AS GroupName,
#GroupId AS GroupId,
CASE GROUPING(u.UserId) WHEN 1 THEN NULL ELSE MIN(u.Consultant) END AS Consultant,
u.UserId,
SUM(COALESCE(cc.ManagerCount, 0)) AS ManagersAdded,
SUM(COALESCE(ip.[1], 0)) AS FirstInterviewCount,
SUM(COALESCE(ip.[1], 0) + COALESCE(ip.[3], 0) + COALESCE(ip.[4], 0)) AS InterviewCount,
SUM(COALESCE(ip.[2], 0)) AS TelephoneCount
FROM #Users u
LEFT JOIN #ClientContacts cc ON u.UserId = cc.UserId
LEFT JOIN (SELECT i.UserId, i.InterviewTypeId, i.InterviewCount
FROM #Interviews i) AS ii
PIVOT (SUM(InterviewCount) FOR InterviewTypeId IN ([1], [2], [3], [4])) AS ip ON u.UserId = ip.UserId
GROUP BY ROLLUP(u.UserId)
ORDER BY GROUPING(u.UserId), u.UserId