How can I optimised this query since it is causing locks - sql

Its causing locks and I need help optimising it...
Select o.Vehicle as [No Unit], o.Customer, o.CustomerDisplayName as Name, o.Product as Material, P.ProductName as Product,
o.Depot as Works, a.Distance, o.CustTravelTime as [Assumed TravelTime], o.RequiredDateTime as [Required DateTime],o.TimeWindowOrder
as [To Window Provided],ToWindowDateTime as [Window DateTime],o.OrderRef as [Ref No], o.OrderEntryDateTime as [Orderred DateTime],
o.EnteredBy, o.Instructions, o.Warnings, o.Planning, o.AllocationState as Status,o.LoadDocket as Docket, o.LoadingDateTime
as [Commenced Loading], o.IntransitDateTime as [Completed Loading], o.ArrivedDateTime as [Arrived Customer], o.ArrivedDateTime
as [Commenced Unloading], o.UnloadedDateTime as [Completed Unloading], '?' as [DMS], o.CustomerOrder as CustPO,
o.Renegotiated, o.TurnAround, o.StockOut, o.LateDelivery,o.LateOrder,o.StandingOrder,o.NightShift,o.modifier
as [Actual Modifier], t2.Net, t2.Trantype,o.PlannedDateTime, o.VehAssignedDateTime as [Published Date],
t2.DriverName, o.CancelledDateTime from Orders o left outer join Product P on p.Product = o.Product
left outer join AuthPlantCust A on a.Customer = o.Customer and a.Plant = o.Plant --left
join trans T on O.orderref = t.orderref
outer apply ( SELECT Top 1 Docket, Trantype, DriverName, Net FROM Trans t where o.Orderref = t.Orderref AND TranType <> 'SRT'
ORDER BY DespatchdateTime Desc ) T2 where o.RequiredDateTime >= (#DespatchFrom)
and o.RequiredDateTime < (#DespatchTo) and o.Company = 'C' order by o.RequiredDateTime, o.OrderRef
Or advise best practices.

Related

Query to get the min date for the duplicate records

Below is my query, if there duplicate records I need to filter based on dates.
select
X.[po number],
(X.[ grn number]),
(X.[grn docentry]),
(X.ItemCode),
(X.[grn total]),
(X.tax),
(x.DocDate)[docdate]
from (
SELECT Distinct
T0.[DocNum] [po number],
T3.[DocNum] [ grn number],
T3.DocEntry [grn docentry],
T1.ItemCOde,
(T3.DocDate),
CASE WHEN T3.DocCur != 'SGD'
then (T4.PriceBefDi * T4.Quantity)
ELSE T4.LineTotal
END [grn total],
CASE WHEN T3.DocCur != 'SGD'
THEN T4.VatSumFrgn
ELSE T4.VatSum
END as [tax]
FROM OPOR T0
INNER JOIN POR1 T1 ON T0.DocEntry = T1.DocEntry
INNER JOIN PDN1 T4 on T1.DocEntry = T4.BaseEntry and T1.LineNum = T4.BaseLine
INNER JOIN OPDN T3 on T3.DocEntry = T4.DocEntry
)X
where X.[po number] in (37199, 37431, 37163, 37163, 37548)
and X.[grn total] in (1350.0000, 650.0000, 140.0000, 372.0000, 685.0000)
Below is my result set. if there are similar item codes, amount, tax amount. I need get only one record based on the minimum date for those matching. The highlighted red color must not show in the result set.
The actual output is like below:
You need to aggregate and select - what looks like - the min of each group:
select X.[po number], Min(X.[grn number])[grn number], Min(X.[grn docentry])[grn docentry], X.ItemCode, X.[grn total], X.tax, Min(X.DocDate) [docdate] from (
select distinct T0.[DocNum] [po number], T3.[DocNum] [ grn number], T3.DocEntry [grn docentry], T1.ItemCOde, T3.DocDate,
case when T3.DocCur != 'SGD' then (T4.PriceBefDi * T4.Quantity) else T4.LineTotal end [grn total] ,
case when T3.DocCur != 'SGD' then T4.VatSumFrgn else T4.VatSum end as [tax]
from OPOR T0
inner join POR1 T1 on T0.DocEntry = T1.DocEntry
inner join PDN1 T4 on T1.DocEntry = T4.BaseEntry and T1.LineNum = T4.BaseLine
inner join OPDN T3 on T3.DocEntry = T4.DocEntry
)X
where X.[po number] in (37199, 37431, 37163, 37163, 37548) and X.[grn total] in (1350.0000, 650.0000, 140.0000, 372.0000, 685.0000)
group by X.[po number], X.ItemCode, X.[grn total], X.tax
Use GROUP BY for and set HAVING clause MIN(x.DocDate).
I guess that your unique column is x.ItemCode and add the rest of column.
Sample:
GROUP BY x.ItemCode
HAVING MIN(x.DocDate)
One way is
select top(1) with ties *
from (
-- your original query
) t
order by row_number() over(partition by ItemCode, [grn total], tax order by docdate)

SQL Server: stored procedure performance between UNION ALL of two statements vs ROLLUP

I have been tasked with improving the performance of a stored procedure that uses a UNION ALL of two statements to retrieve the desired results. In my travels, I've come across the idea of using WITH ROLLUPas an alternative to help performance. I'm decent at SQL, but I think I need a little help with this one. (I'm also new here so I'm not as familiar with the Db as I'd like.)
It is selecting from basically, the same places in both statements as you can see by the joins. But the conditions are a little different between them. One join in the second statement has <> 'zzzCUSTOM' but the corresponding first statement doesn't have this, as an example. I think there's a better way to write this so as to not need the UNION ALL, maybe by combining the conditions/joins into one statement since it's all adding together (UNION ALL) anyway?... Other ideas?
The stored procedure is also built with dynamic SQL so it's a bit hard to follow. Here it is as regular SQL (with all the variables filled in):
SELECT
[SKU No], [SKN], [Description], [Orders],
[Quantity], [Unit Price], [Total Price]
FROM
(SELECT
1 AS TOT,
'Totals:' AS [SKU No],
'' AS [SKN],
'' AS [DESCRIPTION],
isnull(SUM([Orders]), 0) AS [Orders],
isnull(SUM([Quantity]), 0) AS [Quantity],
isnull(SUM([Unit Price]), 0) AS [Unit Price],
isnull(SUM([Total Price]), 0) AS [Total Price]
FROM
(SELECT
COUNT(distinct o.orderno) AS [Orders],
SUM(oi.quantity) as [Quantity],
oi.unitprice AS [Unit Price],
SUM(oi.extprice) AS [Total Price]
FROM
orderupdates ou
INNER JOIN
orders o ON o.orderno = ou.orderno
INNER JOIN
orderdetails od ON od.orderno = o.orderno
INNER JOIN
orderitems oi ON oi.orderno = o.orderno
AND oi.linenum = od.linenum
INNER JOIN
items i ON i.itemid = od.itemid
WHERE
actdate >= '2015-05-01'
AND ou.actdate < '2015-05-15'
AND type = 0
GROUP BY
oi.unitprice, i.skuno, i.description) S
union all
select 0 AS TOT,
isnull(i.skuno,'') as [SKU No],
isnull(vi.SKUNo,'')AS [SKN],
isnull(i.description,'')AS [DESCRIPTION],
count(distinct o.orderno) AS [Orders],
isnull(sum(isnull(oi.quantity,0)),0) as [Quantity],
isnull(oi.unitprice,0)AS [Unit Price],
isnull(sum(isnull(oi.extprice,0)),0)AS [Total Price]
from
orderupdates as ou
inner join orders o on o.orderno = ou.orderno and o.orderno <> 'ZZZCUSTOM'
inner join orderdetails od on od.orderno = o.orderno
inner join orderitems oi on oi.orderno = o.orderno and oi.linenum = od.linenum
inner join items i on i.itemid = od.itemid
inner join vendoritems vi ON vi.ItemId=i.ItemId
left outer join VendorBuyers BORD on BORD.Buyer = 'admin' and BORD.Usage = 10000 and BORD.VendorNo = O.VendorNo and BORD.fgSpecialPO = O.fgSpecialPO
where
case when BORD.EMailId is null then
case when IsNull(BORD.Type, 0) = 1 then 1
when O.fgSpecialPO in (0, 2, 4) then 1
when O.fgSpecialPO in (1, 3, 5) then 1 end
else 0 end = 1
and O.fgSpecialPO IN (0)
and ou.actdate >= '2015-05-01'
and ou.actdate < '2015-05-15'
and ou.type = 0
group by i.skuno, vi.skuno, i.description, oi.unitprice ) T
ORDER BY
TOT, [Quantity] DESC, [SKU No]
Look to use GROUPING SETS instead. This give more flexibility than ROLLUP
GROUP BY
GROUPING SETS (
(oi.unitprice, i.skuno, i.description),
(i.skuno, vi.skuno, i.description, oi.unitprice)
)
there will need to be a few extra tweaks, such as a few ISNULL(A,'') AS A, etc, buy hopefully this will get you moving in the right direction.
See https://technet.microsoft.com/en-us/library/bb510427%28v=sql.105%29.aspx?f=255&MSPPError=-2147217396 for more and some equivalence examples.
I would take a look at the sub queries first. In the inner sub query of the top part of the union is going a group by i.description, but the description field is not used in the select statement. The item table is also referenced in the statement, but is not needed.
SELECT
COUNT(distinct o.orderno) AS [Orders],
SUM(oi.quantity) as [Quantity],
oi.unitprice AS [Unit Price],
SUM(oi.extprice) AS [Total Price]
FROM
orderupdates ou
INNER JOIN
orders o ON o.orderno = ou.orderno
INNER JOIN
orderdetails od ON od.orderno = o.orderno
INNER JOIN
orderitems oi ON oi.orderno = o.orderno
AND oi.linenum = od.linenum
--INNER JOIN
--items i ON i.itemid = od.itemid
WHERE
actdate >= '2015-05-01'
AND ou.actdate < '2015-05-15'
AND type = 0
GROUP BY
oi.unitprice, i.skuno --, i.description
There are more optimizations that can be done to your SQL statement.

SQL: How do I show all Items in Inventory and Sum sales of items sold in a time period?

I am trying to find all items on hand from #Supplier_ID and summarize any sales since #Begin_Date. What is returned are all items on hand that have never been sold and those sold since #Begin_Date. Items on hand that were sold before #Begin_Date are excluded from the results. How do I fix that?
I am using SQL Server 2012 and SSRS v3.
SELECT DISTINCT
inventory_supplier.supplier_id AS [Supp ID],
address.name AS Supplier,
inv_loc.location_id AS [Inventory Loc ID],
inv_mast.item_id AS [Item ID],
inv_mast.item_desc AS [Item Desc],
inv_loc.qty_on_hand AS QOH,
inv_loc.moving_average_cost AS MAC,
invoice_line.qty_shipped,
invoice_hdr.customer_id AS [Customer ID],
invoice_hdr.bill2_name AS Customer,
oe_line.source_loc_id AS [Sales Source Loc]
FROM
inventory_supplier
INNER JOIN
inv_mast ON inventory_supplier.inv_mast_uid = inv_mast.inv_mast_uid
INNER JOIN
address ON inventory_supplier.supplier_id = address.id
FULL OUTER JOIN
invoice_line ON inv_mast.inv_mast_uid = invoice_line.inv_mast_uid
FULL OUTER JOIN
inv_loc ON inv_mast.inv_mast_uid = inv_loc.inv_mast_uid
FULL OUTER JOIN
invoice_hdr ON invoice_line.invoice_no = invoice_hdr.invoice_no
FULL OUTER JOIN
oe_line ON invoice_hdr.order_no = oe_line.order_no
AND invoice_line.inv_mast_uid = oe_line.inv_mast_uid
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date
OR invoice_hdr.invoice_date IS NULL)
AND (inv_loc.qty_on_hand > 0)
ORDER BY
[Item ID], [Inventory Loc ID], [Customer ID], [Sales Source Loc]
You could move your invoice_hdr.invoice_date >= #Begin_Date to your join statement
FULL OUTER JOIN
invoice_hdr ON invoice_line.invoice_no = invoice_hdr.invoice_no
AND invoice_hdr.invoice_date >= #Begin_Date
Don't see a lot of FULL OUTER JOINs. Sure you don't want LEFT JOIN here?
You might want to separate out the Invoice information from the Inventory information into a subquery, and LEFT JOIN to the Invoice information.
SELECT DISTINCT
inventory_supplier.supplier_id AS [Supp ID],
address.name AS Supplier,
inv_loc.location_id AS [Inventory Loc ID],
inv_mast.item_id AS [Item ID],
inv_mast.item_desc AS [Item Desc],
inv_loc.qty_on_hand AS QOH,
inv_loc.moving_average_cost AS MAC,
invoices.qty_shipped,
invoices.customer_id AS [Customer ID],
invoices.bill2_name AS Customer,
invoices.source_loc_id AS [Sales Source Loc]
FROM
inventory_supplier
INNER JOIN
inv_mast ON inventory_supplier.inv_mast_uid = inv_mast.inv_mast_uid
INNER JOIN
address ON inventory_supplier.supplier_id = address.id
INNER JOIN
inv_loc ON inv_mast.inv_mast_uid = inv_loc.inv_mast_uid
LEFT OUTER JOIN
(SELECT
invoice_line.inv_mast_uid,
invoice_line.qty_shipped,
invoice_hdr.customer_id,
invoice_hdr.bill2_name,
oe_line.source_loc_id
FROM
invoice_line
INNER JOIN
invoice_hdr ON invoice_line.invoice_no = invoice_hdr.invoice_no
INNER JOIN
oe_line ON invoice_hdr.order_no = oe_line.order_no
AND invoice_line.inv_mast_uid = oe_line.inv_mast_uid
WHERE
invoice_hdr.invoice_date >= #Begin_Date
) invoices ON invoices.inv_mast_uid = inv_mast.inv_mast_uid
WHERE
inventory_supplier.supplier_id = #Supplier_ID
AND inv_loc.qty_on_hand > 0
ORDER BY
[Item ID], [Inventory Loc ID], [Customer ID], [Sales Source Loc]
Try changing
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date
OR invoice_hdr.invoice_date IS NULL)
AND (inv_loc.qty_on_hand > 0)
to
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date)
AND (inv_loc.qty_on_hand > 0)
The problem is because you are including dates, invoice_hdr.invoice_date that are NULL in the WHERE clause. Simply remove it:
WHERE
(inventory_supplier.supplier_id = #Supplier_ID)
AND (invoice_hdr.invoice_date >= #Begin_Date)
AND (inv_loc.qty_on_hand > 0)

SQL select statement that checks two columns and returns the value from a third [duplicate]

This question already has answers here:
SQL Server Error:"SQL Server Subquery returned more than 1 value"
(2 answers)
Closed 7 years ago.
I am writing a query that accesses multiple tables in the same database. For one of the columns in the select statement, I need to return
Table1.Column4
where Table1.Column = Table3.Column1 AND
Table1.Column2 = Table4.Column1
I have it written as:
SELECT AccNum.FieldValue
FROM PersonFieldValuesVW
INNER JOIN PersonFieldValuesVW AccNum
ON AccNum.PersonId = InPerson.PersonId
INNER JOIN InPerson
ON InPerson.IncidentId = Incident.Id
WHERE AccNum.FieldDescr like '%Account Number%') as [Account Number],
This is returning the error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
Here is the full query, any assistance would be appreciated.
SELECT DISTINCT
CaseNum as [Case Number],
ALCategoryVW.Category as [Category],
ALCategoryVW.SubCategory as [Sub Category],
InAssign.AssignToName as [Assigned To],
ReportedDate as [Open Date],
EndDate as [Closed Date], --This a placeholder for a closed date
[Status],
SiteLoc1.Descr as [Loss Location],
LocDetails as [Loss Cost Center],
SiteLoc1.Region as [Region],
SiteLoc1.SubRegion as [Sub Region],
-- SiteLoc2.Descr as [Location Description], **Need this though returning all for the location?
CASE WHEN SAR.FieldId = '604NU' and SAR.FieldValue <> 'False' THEN 'YES' ELSE 'NO' END as [SAR Required],
Summary as [Incident Summary],
Disposition as [Case Disposition],
(
SELECT AccNum.FieldValue
FROM PersonFieldValuesVW
INNER JOIN PersonFieldValuesVW AccNum ON AccNum.PersonId = InPerson.PersonId
INNER JOIN InPerson ON InPerson.IncidentId = Incident.Id
WHERE AccNum.FieldDescr like '%Account Number%'
) as [Account Number],
FORMAT(AuditItemDetail.ItemValue, '#,###') as [Potential Loss],
FORMAT(AuditItemDetail.ItemValue - AuditItemDetail.PreventedExposureAmount, '#,###') as [Actual Loss]
FROM Incident
INNER JOIN ALCategoryVW ON ALCategoryVW.IncidentId = Incident.Id
INNER JOIN InAssign ON InAssign.IncidentId = Incident.Id
INNER JOIN SiteLoc1 ON SiteLoc1.Id = Incident.LocId
INNER JOIN SiteLoc2 ON SiteLoc2.SiteLoc1Id = SiteLoc1.Id
INNER JOIN IncidentFieldValuesVW SAR ON SAR.IncidentId = Incident.Id
INNER JOIN InItem ON InItem.IncidentId = Incident.Id
INNER JOIN AuditItemDetail ON AuditItemDetail.ItemId = InItem.ItemId
INNER JOIN InPerson ON InPerson.IncidentId = Incident.Id
INNER JOIN PersonFieldValuesVW AccNum ON AccNum.PersonId = InPerson.PersonId
This should resolve your error, but I'm not sure it is logically correct. If you have two records being returned in the sub-select, which one is the "right" one.
SELECT DISTINCT
CaseNum as [Case Number],
ALCategoryVW.Category as [Category],
ALCategoryVW.SubCategory as [Sub Category],
InAssign.AssignToName as [Assigned To],
ReportedDate as [Open Date],
EndDate as [Closed Date], --This a placeholder for a closed date
[Status],
SiteLoc1.Descr as [Loss Location],
LocDetails as [Loss Cost Center],
SiteLoc1.Region as [Region],
SiteLoc1.SubRegion as [Sub Region],
-- SiteLoc2.Descr as [Location Description], **Need this though returning all for the location?
CASE WHEN SAR.FieldId = '604NU' and SAR.FieldValue <> 'False' THEN 'YES' ELSE 'NO' END as [SAR Required],
Summary as [Incident Summary],
Disposition as [Case Disposition],
AccNum.FieldValue,
FORMAT(AuditItemDetail.ItemValue, '#,###') as [Potential Loss],
FORMAT(AuditItemDetail.ItemValue - AuditItemDetail.PreventedExposureAmount, '#,###') as [Actual Loss]
FROM Incident
INNER JOIN ALCategoryVW ON ALCategoryVW.IncidentId = Incident.Id
INNER JOIN InAssign ON InAssign.IncidentId = Incident.Id
INNER JOIN SiteLoc1 ON SiteLoc1.Id = Incident.LocId
INNER JOIN SiteLoc2 ON SiteLoc2.SiteLoc1Id = SiteLoc1.Id
INNER JOIN IncidentFieldValuesVW SAR ON SAR.IncidentId = Incident.Id
INNER JOIN InItem ON InItem.IncidentId = Incident.Id
INNER JOIN AuditItemDetail ON AuditItemDetail.ItemId = InItem.ItemId
INNER JOIN InPerson ON InPerson.IncidentId = Incident.Id
LEFT JOIN PersonFieldValuesVW AccNum ON AccNum.PersonId = InPerson.PersonId AND AccNum.FieldDescr like '%Account Number%'
***Updated based on comment.

Selecting most recent record in large query based on one value in SELECT field

I have a large query, well relatively large. This query constantly produces multiple results on the MATERIAL column even though I have specified 'DISTINCT'. I thought by specifying 'DISTINCT' and summing the values I needed that it would produce one line per MATERIAL number. Can anybody help me see what I am doing wrong here. I realize the last sub query might be redundant at this point - I was testing and this is what was producing the result I was getting.
Thanks ahead of time.
DECLARE #daynumber as int
SET #daynumber = CASE
WHEN DATENAME(dw,GETDATE()) = 'Monday'
THEN 56
WHEN DATENAME(dw,GETDATE()) = 'Tuesday'
THEN 57
WHEN DATENAME(dw,GETDATE()) = 'Wednesday'
THEN 58
WHEN DATENAME(dw,GETDATE()) = 'Thursday'
THEN 59
WHEN DATENAME(dw,GETDATE()) = 'Friday'
THEN 60
END;
SELECT DISTINCT MATERIAL,
PLANT_CODE,
STOCK_CATEGORY,
material_desc AS 'MATERIAL_DESC',
division_id AS 'DIVISION_ID',
UPPER(division_desc) AS 'DIVISION_DESC',
UPPER(gender_id) AS 'GENDER_ID',
UPPER(gender_desc) AS 'GENDER_DESC',
DISTRIBUTION_VERSION_CODE,
PERIOD_CODE,
REQUIREMENTS_DATE,
VERSION_IND_FLAG,
TECHNICAL_INDEX,
SIZE_LITERAL,
[ORIGINAL FCST QTY],
WITHDRAWN_QUANTITY,
[REM PLAN QTY],
FUTURE_FCST,
TOTAL_OH_INV
FROM (
SELECT P1.PLANT_CODE,
P1.STOCK_CATEGORY,
P1.MATERIAL,
M1.material_desc AS 'MATERIAL_DESC',
M1.division_id AS 'DIVISION_ID',
UPPER(M1.division_desc) AS 'DIVISION_DESC',
UPPER(M1.gender_id) AS 'GENDER_ID',
UPPER(M1.gender_desc) AS 'GENDER_DESC',
P1.DISTRIBUTION_VERSION_CODE,
P1.PERIOD_CODE,
P1.REQUIREMENTS_DATE,
P1.VERSION_IND_FLAG,
P1.TECHNICAL_INDEX,
P1.SIZE_LITERAL,
P1.[ORIGINAL FCST QTY],
P1.WITHDRAWN_QUANTITY,
P1.[REM PLAN QTY],
P2.FUTURE_FCST,
SUM(I1.ON_HAND_QUANTITY) AS 'TOTAL_OH_INV'
FROM
(SELECT PLANT_CODE,
STOCK_CATEGORY,
MATERIAL,
DISTRIBUTION_VERSION_CODE,
PERIOD_CODE,
REQUIREMENTS_DATE,
PLANNED_QTY AS 'REM PLAN QTY',
VERSION_IND_FLAG,
SIZE_LITERAL,
WITHDRAWN_QUANTITY,
TECHNICAL_INDEX,
PLANNED_QTY + WITHDRAWN_QUANTITY AS 'ORIGINAL FCST QTY'
FROM VW_PLANNED_REQMNTS_TXT
WHERE PLANT_CODE IN ('6040','6041')
AND STOCK_CATEGORY IN ('A60385000','A60385003')
AND DISTRIBUTION_VERSION_CODE IN ('00','01','ZU','Z2')
AND REQUIREMENTS_DATE < GETDATE() - #daynumber
AND PLANNED_QTY > 0) AS P1
LEFT OUTER JOIN
(SELECT
SUM(PLANNED_QTY) AS 'FUTURE_FCST',
MATERIAL,
TECHNICAL_INDEX
FROM VW_PLANNED_REQMNTS_TXT P
WHERE REQUIREMENTS_DATE >= GETDATE()
AND PLANNED_QTY > 0
AND STOCK_CATEGORY IN ('A60385000','A60385003')
GROUP BY MATERIAL,
TECHNICAL_INDEX,
SIZE_LITERAL) AS P2
ON P1.MATERIAL = P2.MATERIAL
AND P1.TECHNICAL_INDEX = P2.TECHNICAL_INDEX
LEFT OUTER JOIN
(SELECT ON_HAND_QUANTITY,
TECHNICAL_INDEX,
MATERIAL,
STOCK_CATEGORY,
PLANT_CODE
FROM VW_INVENTORY I
WHERE STOCK_CATEGORY IN ('A60385000','A60385003')
GROUP BY TECHNICAL_INDEX,
MATERIAL,
STOCK_CATEGORY,
ON_HAND_QUANTITY,
PLANT_CODE) AS I1
ON P1.MATERIAL = I1.MATERIAL
AND P1.TECHNICAL_INDEX = I1.TECHNICAL_INDEX
AND P1.PLANT_CODE = I1.PLANT_CODE
LEFT OUTER JOIN
(SELECT M.material_number,
M.material_desc,
M.division_id,
D.division_desc,
M.gender_id,
G.gender_desc
FROM MaterialMaster.dbo.Material M
JOIN MaterialMaster.dbo.Ref_Division D
ON M.division_id = D.division_id
JOIN MaterialMaster.dbo.Ref_Gender G
ON M.gender_id = G.gender_id) AS M1
ON P1.MATERIAL = M1.material_number
GROUP BY P1.PLANT_CODE,
P1.STOCK_CATEGORY,
P1.MATERIAL,
P1.DISTRIBUTION_VERSION_CODE,
P1.PERIOD_CODE,
P1.REQUIREMENTS_DATE,
P1.[REM PLAN QTY],
P1.VERSION_IND_FLAG,
P1.WITHDRAWN_QUANTITY,
P1.SIZE_LITERAL,
P1.TECHNICAL_INDEX,
P1.[ORIGINAL FCST QTY],
P2.FUTURE_FCST,
M1.material_desc,
M1.division_id,
M1.division_desc,
M1.gender_id,
M1.gender_desc) AS T1 /* T1 Represents "Total" for all */
GROUP BY PLANT_CODE,
STOCK_CATEGORY,
MATERIAL,
material_desc,
division_id,
division_desc,
gender_id,
gender_desc,
DISTRIBUTION_VERSION_CODE,
PERIOD_CODE,
REQUIREMENTS_DATE,
VERSION_IND_FLAG,
TECHNICAL_INDEX,
SIZE_LITERAL,
[ORIGINAL FCST QTY],
WITHDRAWN_QUANTITY,
[REM PLAN QTY],
FUTURE_FCST,
TOTAL_OH_INV
You use 2 times GROUP BY clause that does the same thing. The outer GROUP BY has no effect. Moreover using DISTINCT when you have already used GROUP BY means, that somethig is wrong, as #mason pointed out in his comment. You have tried to remove some rows but it is not a good way to go, it only obfuscates the problem.
Another recommendation: for field names use [ and ] chars instead of ' chars, e.g. M1.material_desc AS [MATERIAL_DESC]. It will improve readability of your SQL which is something you need badly writing longer queries - char literals are in red.
So the inner query - the problematic part - should be reformatted like this to be readable:
SELECT P1.PLANT_CODE, P1.STOCK_CATEGORY, P1.MATERIAL, M1.material_desc AS [MATERIAL_DESC], M1.division_id AS [DIVISION_ID],
UPPER(M1.division_desc) AS [DIVISION_DESC], UPPER(M1.gender_id) AS [GENDER_ID], UPPER(M1.gender_desc) AS [GENDER_DESC],
P1.DISTRIBUTION_VERSION_CODE, P1.PERIOD_CODE, P1.REQUIREMENTS_DATE, P1.VERSION_IND_FLAG, P1.TECHNICAL_INDEX, P1.SIZE_LITERAL,
P1.[ORIGINAL FCST QTY], P1.WITHDRAWN_QUANTITY, P1.[REM PLAN QTY], P2.[FUTURE_FCST], SUM(I1.ON_HAND_QUANTITY)
AS [TOTAL_OH_INV]
FROM (SELECT PLANT_CODE, STOCK_CATEGORY, MATERIAL, DISTRIBUTION_VERSION_CODE, PERIOD_CODE, REQUIREMENTS_DATE,
PLANNED_QTY AS [REM PLAN QTY], VERSION_IND_FLAG, SIZE_LITERAL, WITHDRAWN_QUANTITY, TECHNICAL_INDEX,
PLANNED_QTY + WITHDRAWN_QUANTITY AS [ORIGINAL FCST QTY]
FROM VW_PLANNED_REQMNTS_TXT
WHERE (PLANT_CODE IN ('6040', '6041')) AND (STOCK_CATEGORY IN ('A60385000', 'A60385003'))
AND (DISTRIBUTION_VERSION_CODE IN ('00', '01', 'ZU', 'Z2'))
AND (REQUIREMENTS_DATE < GETDATE() - #daynumber) AND (PLANNED_QTY > 0)
) AS P1 LEFT OUTER JOIN
(SELECT SUM(PLANNED_QTY) AS [FUTURE_FCST], MATERIAL, TECHNICAL_INDEX
FROM VW_PLANNED_REQMNTS_TXT AS P
WHERE (REQUIREMENTS_DATE >= GETDATE()) AND (PLANNED_QTY > 0)
AND (STOCK_CATEGORY IN ('A60385000', 'A60385003'))
GROUP BY MATERIAL, TECHNICAL_INDEX, SIZE_LITERAL
) AS P2 ON P1.MATERIAL = P2.MATERIAL AND P1.TECHNICAL_INDEX = P2.TECHNICAL_INDEX
LEFT OUTER JOIN
(SELECT ON_HAND_QUANTITY, TECHNICAL_INDEX, MATERIAL, STOCK_CATEGORY, PLANT_CODE
FROM VW_INVENTORY AS I
WHERE (STOCK_CATEGORY IN ('A60385000', 'A60385003'))
GROUP BY TECHNICAL_INDEX, MATERIAL, STOCK_CATEGORY, ON_HAND_QUANTITY, PLANT_CODE
) AS I1 ON P1.MATERIAL = I1.MATERIAL AND P1.TECHNICAL_INDEX = I1.TECHNICAL_INDEX AND P1.PLANT_CODE = I1.PLANT_CODE
LEFT OUTER JOIN
(SELECT M.material_number, M.material_desc, M.division_id, D.division_desc, M.gender_id, G.gender_desc
FROM MaterialMaster.dbo.Material AS M
INNER JOIN MaterialMaster.dbo.Ref_Division AS D ON M.division_id = D.division_id
INNER JOIN MaterialMaster.dbo.Ref_Gender AS G ON M.gender_id = G.gender_id
) AS M1 ON P1.MATERIAL = M1.material_number
GROUP BY PLANT_CODE, STOCK_CATEGORY, MATERIAL, DISTRIBUTION_VERSION_CODE, PERIOD_CODE, REQUIREMENTS_DATE,
P1.[REM PLAN QTY], P1.VERSION_IND_FLAG, P1.WITHDRAWN_QUANTITY, P1.SIZE_LITERAL, P1.TECHNICAL_INDEX, P1.[ORIGINAL FCST QTY],
P2.[FUTURE_FCST], M1.material_desc, M1.division_id, M1.division_desc, M1.gender_id, M1.gender_desc
Here you should look for your problem.
Check every inner SELECT separately a verify if it is returning desired results. The problem could be that you have twice SELECT from VW_PLANNED_REQMNTS_TXT. I suggest that you try to remove P2 subquery and see what happens. Why P2 is not a part of P1 subquery?
FROM (SELECT PLANT_CODE, STOCK_CATEGORY, MATERIAL, DISTRIBUTION_VERSION_CODE, PERIOD_CODE, REQUIREMENTS_DATE,
PLANNED_QTY AS [REM PLAN QTY], VERSION_IND_FLAG, SIZE_LITERAL, WITHDRAWN_QUANTITY, TECHNICAL_INDEX,
PLANNED_QTY + WITHDRAWN_QUANTITY AS [ORIGINAL FCST QTY]
(SELECT SUM(PLANNED_QTY)
FROM VW_PLANNED_REQMNTS_TXT
WHERE (REQUIREMENTS_DATE >= GETDATE()) AND (PLANNED_QTY > 0)
AND (STOCK_CATEGORY IN ('A60385000', 'A60385003'))
AND MATERIAL=P.MATERIAL AND TECHNICAL_INDEX=P.TECHNICAL_INDEX
GROUP BY SIZE_LITERAL) AS [FUTURE_FCST]
FROM VW_PLANNED_REQMNTS_TXT P
WHERE (PLANT_CODE IN ('6040', '6041')) AND (STOCK_CATEGORY IN ('A60385000', 'A60385003'))
AND (DISTRIBUTION_VERSION_CODE IN ('00', '01', 'ZU', 'Z2'))
AND (REQUIREMENTS_DATE < GETDATE() - #daynumber) AND (PLANNED_QTY > 0)
) AS P1
LEFT OUTER JOIN
(SELECT ON_HAND_QUANTITY, TECHNICAL_INDEX, MATERIAL, STOCK_CATEGORY, PLANT_CODE
Also LEFT OUTER JOIN can produce rows without any MATERIAL. Why not INNER JOIN?
But your problem cannot be solved miraculously in the final GROUP BY clause, because there you only SUM one field of all selected fields.