I'm trying to write a query which will do some calculations on a transaction if that specific transaction meets a certain requirement (in this case that it's total quantity != 0).
IF EXISTS(
SELECT DISTINCT
T0.[ItemCode],
T0.[ItemName],
T0.[DocDate],
CAST(CAST(T0.[CreateTime] / 100 AS varchar) + ':' + CAST(T0.[CreateTime] % 100 AS varchar) AS time) AS [CreateTime],
T0.[DocType],
T0.[DocEntry],
T0.[DocNum],
T0.[LocCode],
T1.[MdAbsEntry],
T4.[AbsEntry],
T4.[DistNumber] AS [BatchNumber],
T1.[Quantity],
T5.[CalcPrice] AS [Price],
T3.[U_ORC_BE_Variance]
FROM OITL T0
INNER JOIN ITL1 T1 ON T1.[LogEntry] = T0.[LogEntry]
INNER JOIN OITM T2 ON T2.[ItemCode] = T0.[ItemCode]
INNER JOIN IGE1 T3 ON T3.[DocEntry] = T0.[DocEntry]
INNER JOIN OBTN T4 ON T1.[MdAbsEntry] = T4.[AbsEntry]
INNER JOIN OINM T5 ON T0.[ItemCode] = T5.[ItemCode]
AND T0.[LocCode] = T5.[Warehouse]
AND T0.[AppDocNum] = T5.[BASE_REF]
WHERE T0.[ItemCode] LIKE 'BB%' -- BBT items only
AND T3.[U_ORC_BE_Variance] = 'M3'-- Code issued upon BBT empty
AND CAST(CAST(T0.[CreateTime] / 100 AS varchar) + ':' + CAST(T0.[CreateTime] % 100 AS varchar) AS time)
BETWEEN CAST(DATEADD(MINUTE,-11,GETDATE())AS TIME) AND CONVERT(varchar(10), GETDATE(), 108) -- Last 10 minutes
AND T0.[DocDate] = CAST(LEFT(GETDATE(), 11) AS DATETIME) -- Today
)
BEGIN
SELECT DISTINCT
'BBT ALERT - ' + convert(varchar(10), GETDATE(), 108) + ' - Check for errors',
'Difference HL:',
SUM(T1.[Quantity]),
'Percentage Difference:',
((((SUM(ABS(T1.[Quantity])) - MAX(T1.[Quantity])) / MAX(T1.[Quantity])) * 100) - 100)
FROM OITL T0
INNER JOIN ITL1 T1 ON T1.[LogEntry] = T0.[LogEntry]
INNER JOIN OITM T2 ON T2.[ItemCode] = T0.[ItemCode]
INNER JOIN IGE1 T3 ON T3.[DocEntry] = T0.[DocEntry]
INNER JOIN OBTN T4 ON T1.[MdAbsEntry] = T4.[AbsEntry]
INNER JOIN OINM T5 ON T0.[ItemCode] = T5.[ItemCode]
AND T0.[LocCode] = T5.[Warehouse]
AND T0.[AppDocNum] = T5.[BASE_REF]
WHERE
(SELECT SUM([Quantity]) FROM ITL1 WHERE
(SELECT DISTINCT
T4.[AbsEntry]
FROM OITL T0
INNER JOIN ITL1 T1 ON T1.[LogEntry] = T0.[LogEntry]
INNER JOIN OITM T2 ON T2.[ItemCode] = T0.[ItemCode]
INNER JOIN IGE1 T3 ON T3.[DocEntry] = T0.[DocEntry]
INNER JOIN OBTN T4 ON T1.[MdAbsEntry] = T4.[AbsEntry]
INNER JOIN OINM T5 ON T0.[ItemCode] = T5.[ItemCode]
AND T0.[LocCode] = T5.[Warehouse]
AND T0.[AppDocNum] = T5.[BASE_REF]
WHERE T0.[ItemCode] LIKE 'BB%' -- BBT items only
AND T3.[U_ORC_BE_Variance] = 'M3'-- Code issued upon BBT empty
AND CAST(CAST(T0.[CreateTime] / 100 AS varchar) + ':' + CAST(T0.[CreateTime] % 100 AS varchar) AS time)
BETWEEN CAST(DATEADD(MINUTE,-11,GETDATE())AS TIME) AND CONVERT(varchar(10), GETDATE(), 108) -- Last 10 minutes
AND T0.[DocDate] = CAST(LEFT(GETDATE(), 11) AS DATETIME) -- Today
) = [MdAbsEntry]
) <> 0
SELECT DISTINCT
T1.[MdAbsEntry],
T0.[DocNum],
T1.[Quantity]
FROM OITL T0
INNER JOIN ITL1 T1 ON T1.[LogEntry] = T0.[LogEntry]
INNER JOIN OITM T2 ON T2.[ItemCode] = T0.[ItemCode]
INNER JOIN IGE1 T3 ON T3.[DocEntry] = T0.[DocEntry]
INNER JOIN OBTN T4 ON T1.[MdAbsEntry] = T4.[AbsEntry]
INNER JOIN OINM T5 ON T0.[ItemCode] = T5.[ItemCode] AND T0.[LocCode] = T5.[Warehouse]
AND T0.[AppDocNum] = T5.[BASE_REF]
WHERE
(SELECT SUM([Quantity]) FROM ITL1 WHERE
(SELECT DISTINCT
T4.[AbsEntry]
FROM OITL T0
INNER JOIN ITL1 T1 ON T1.[LogEntry] = T0.[LogEntry]
INNER JOIN OITM T2 ON T2.[ItemCode] = T0.[ItemCode]
INNER JOIN IGE1 T3 ON T3.[DocEntry] = T0.[DocEntry]
INNER JOIN OBTN T4 ON T1.[MdAbsEntry] = T4.[AbsEntry]
INNER JOIN OINM T5 ON T0.[ItemCode] = T5.[ItemCode]
AND T0.[LocCode] = T5.[Warehouse]
AND T0.[AppDocNum] = T5.[BASE_REF]
WHERE T0.[ItemCode] LIKE 'BB%' -- BBT items only
AND T3.[U_ORC_BE_Variance] = 'M3'-- Code issued upon BBT empty
AND CAST(CAST(T0.[CreateTime] / 100 AS varchar) + ':' + CAST(T0.[CreateTime] % 100 AS varchar) AS time)
BETWEEN CAST(DATEADD(MINUTE,-11,GETDATE())AS TIME) AND CONVERT(varchar(10), GETDATE(), 108) -- Last 10 minutes
AND T0.[DocDate] = CAST(LEFT(GETDATE(), 11) AS DATETIME) -- Today
) = [MdAbsEntry]
) <> 0
END
If I run the first part in isolation I get the following (which is correct):
However if I run the query in full I get the following:
I would expect it to only list results with one value in MdAbsEntry (in this case 5618).
It looks to me that it's not matching on the MdAbsEntry value like I want it to, and so pulling results for all data instead of just for this one specific transaction.
Can anyone give me any advice on why it might be doing this?
Related
I have a very simple Inventory in Warehouse query, and now I need to do a sum in the IsCommitted column with another query that I have called "Set Demand".
Like this = Sum( [IsCommited] + "Set Demand Query qty")
Warehouse query
SELECT T0.[ItemCode] AS 'Item No.',
T0.[WhsCode] AS 'Warehouse Code',
T0.[OnHand] AS 'In Stock',
T0.[IsCommited] AS 'Committed',
T0.[MinStock] AS 'Minimum Inventory',
T0.[MaxStock] AS 'Maximum Inventory',
T1.[ItmsGrpCod] AS 'Itemcode',
T2.Price AS 'StandardCost'
FROM [OITW] T0 INNER JOIN [OITM] T1 ON T0.ItemCode = T1.ItemCode LEFT JOIN [ITM1] T2 ON T1.ItemCode = T2.ItemCode and T2.PriceList = 26
WHERE (T0.[WhsCode] = (N'9500' )) AND (T1.[ItmsGrpCod] = (N'100' )) AND T0.[OnHand] > 0
Set Demand query.
SELECT T3.[ItemCode] ,
(-T3.[OnHand] + T1.[Quantity]) as 'Set Demand'
FROM [OITT] T0 WITH (NOLOCK) INNER JOIN [ITT1] T1 WITH (NOLOCK) ON T0.[Code] = T1.[Father], [OSRI] T2 WITH (NOLOCK), [OITW] T3 WITH (NOLOCK) INNER JOIN [OITM] T4 WITH (NOLOCK) ON T3.[ITEMCode] = T4.[ItemCode]
WHERE T0.[Code] = T2.[ItemCode] AND T1.[Code] = T3.[ItemCode] AND T2.[IntrSerial] = T3.[WhsCode] AND T2.[Status] <> 1 and T2.[U_IsCon] <> 'YES' and T3.[OnHand] - T1.[Quantity] < 0 and substring (T2.[WhsCode],8,1)<>'C' AND T2.[WhsCode] = '9000' AND t4.[ItmsGrpCod] = 100
What Im trying to do = ( [IsCommited] + "Set Demand Query qty")
SELECT T0.[ItemCode] AS 'Item No.',
T0.[WhsCode] AS 'Warehouse Code',
T0.[OnHand] AS 'In Stock',
(T0.[IsCommited] + (SELECT (-T3.[OnHand] + T1.[Quantity])
FROM [OITT] T0 WITH (NOLOCK) INNER JOIN [ITT1] T1 WITH (NOLOCK) ON T0.[Code] = T1.[Father], [OSRI] T2 WITH (NOLOCK), [OITW] T3 WITH (NOLOCK) INNER JOIN [OITM] T4 WITH (NOLOCK) ON T3.[ITEMCode] = T4.[ItemCode]
WHERE T0.[Code] = T2.[ItemCode] AND T1.[Code] = T3.[ItemCode] AND T2.[IntrSerial] = T3.[WhsCode] AND T2.[Status] <> 1 and T2.[U_IsCon] <> 'YES' and T3.[OnHand] - T1.[Quantity] < 0 and substring (T2.[WhsCode],8,1)<>'C' AND T2.[WhsCode] = '9000' AND t4.[ItmsGrpCod] = 100) as '**Commited&SetDemand**',
T0.[MinStock] AS 'Minimum Inventory',
T0.[MaxStock] AS 'Maximum Inventory',
T1.[ItmsGrpCod] AS 'Itemcode',
T2.Price AS 'StandardCost'
FROM [OITW] T0 INNER JOIN [OITM] T1 ON T0.ItemCode = T1.ItemCode LEFT JOIN [ITM1] T2 ON T1.ItemCode = T2.ItemCode and T2.PriceList = 26
WHERE (T0.[WhsCode] = (N'9500' )) AND (T1.[ItmsGrpCod] = (N'100' )) AND T0.[OnHand] > 0
Your help will be greatly appreciated. Thank you very much!!!!! :)
Try Something like the Below, I have added the second query with a join on the Item Code.
SELECT T0.[ItemCode] AS 'Item No.',
T0.[WhsCode] AS 'Warehouse Code',
T0.[OnHand] AS 'In Stock',
T0.[IsCommited] AS 'Committed',
T0.[MinStock] AS 'Minimum Inventory',
T0.[MaxStock] AS 'Maximum Inventory',
T1.[ItmsGrpCod] AS 'Itemcode',
T2.Price AS 'StandardCost'
, t0.[IsCommited] + demand.[Set Demand]
FROM [OITW] T0 INNER JOIN [OITM] T1 ON T0.ItemCode = T1.ItemCode LEFT JOIN
[ITM1] T2 ON T1.ItemCode = T2.ItemCode and T2.PriceList = 26
Inner Join
(
SELECT T3.[ItemCode] ,
(-T3.[OnHand] + T1.[Quantity]) as 'Set Demand'
FROM [OITT] T0 WITH (NOLOCK) INNER JOIN [ITT1] T1 WITH (NOLOCK) ON T0.[Code] =
T1.[Father], [OSRI] T2 WITH (NOLOCK), [OITW] T3 WITH (NOLOCK) INNER JOIN [OITM]
T4 WITH (NOLOCK) ON T3.[ITEMCode] = T4.[ItemCode]
WHERE T0.[Code] = T2.[ItemCode] AND T1.[Code] = T3.[ItemCode] AND T2.
[IntrSerial] = T3.[WhsCode] AND T2.[Status] <> 1 and T2.[U_IsCon] <> 'YES' and T3.[OnHand] - T1.
[Quantity] < 0 and substring (T2.[WhsCode],8,1)<>'C' AND T2.[WhsCode] = '9000'
AND t4.[ItmsGrpCod] = 100
) as demand on demand.ItemCode = t0.ItemCode
WHERE (T0.[WhsCode] = (N'9500' )) AND (T1.[ItmsGrpCod] = (N'100' )) AND T0.
[OnHand] > 0
Thank you all for your answers, much appreciated.
And also sorry for my delay in answering.
I was able to solve my problem through this code.
Please look below.
What sawsine said, was exactly that, the relationship between items was missing.
SELECT
OITW.ItemCode,
SUM(CONVERT(INT, (ITT1.quantity - OITW.OnHand))) as 'Set Demand'
FROM OSRI
inner join OSRN on OSRN.ItemCode = OSRI.ItemCode AND OSRN.SysNumber = OSRI.SysSerial
INNER JOIN OITT ON OSRI.ItemCode = OITT.Code
INNER JOIN ITT1 ON ITT1.Father = OITT.Code
INNER JOIN OITW ON ITT1.Code = OITW.ItemCode AND OSRI.IntrSerial = OITW.WhsCode
inner join OWHS on OSRI.WhsCode = OWHS.WhsCode
inner join OITM on ITT1.Code = OITM.ItemCode
WHERE 1=1
AND OSRI.WhsCode = N'9000'
and OSRI.[Status] = 0 and
(OSRN.U_Condition <> N'2' or OSRN.U_Condition is Null) and
OITM.ItmsGrpCod IN (100, 102, 104) and
(LEN(ISNULL(OITM.CardCode,'''')) = 0 or ISNULL(OITM.CardCode,'''') = 'NL20')
AND (ITT1.quantity - OITW.OnHand) > 0
Group by OITW.ItemCode
I have created the following case statement to do some multiplication depending on the items sales unit of measure and for this example, even though I am declaring the SalesUoM Variable as Gallon, it is doing the math for both the gallons and the lbs.
declare #SalesUOM as nvarchar(30)
declare #drumqty as nvarchar(30)
Set #SalesUOM = 'GAL'
Set #drumqty = '3'
SELECT DISTINCT
Case
--- when #SalesUOM = 'DRUM' then ( #drumqty * T1.BaseQty )
-- when #SalesUOM = 'PALLET' then ( #drumqty * T4.BaseQty )
--when #SalesUOM = 'PAIL' then ( #drumqty * T6.BaseQty )
--when #SalesUOM = 'TOTE' then ( #drumqty * T8.BaseQty )
when #SalesUOM = 'LB' then ( #drumqty * T10.BaseQty )
When #SalesUOM = 'GAL' then (#drumQty * T12.BaseQty)
Else '0' End as 'Item Qty'
FROM OUGP T0
--INNER JOIN UGP1 T1 ON T0.[UgpEntry] = T1.[UgpEntry]
--INNER JOIN UGP1 T4 on T0.[UgpEntry] = T4.[UgpEntry]
--INNER JOIN UGP1 T6 on T0.[UgpEntry] = T6.[UgpEntry]
--INNER JOIN UGP1 T8 on T0.UgpEntry = T8.UgpEntry
inner JOIN UGP1 T10 on T0.UgpEntry = T10.UgpEntry
inner JOIN UGP1 T12 on T0.UgpEntry = T12.UgpEntry
--INNER JOIN OUOM T2 ON T0.[BaseUom] = T2.[UomEntry]
--Inner Join OUOM T3 on T1.[UomEntry] = T3.[UomEntry] AND T3.UOMCODE in ('DR-15', 'DR-30', 'DR-55')
--Inner Join OUOM T5 on T4.[UomEntry] = T5.[UomEntry] and T5.UOMCODE = 'PALLET'
--left Join OUOM T7 on T6.UoMEntry = T7.UomEntry and T7.UOMCODE = 'PAIL-5'
--left Join OUOM T9 on T8.UomEntry = T9.UomEntry AND T9.UomCode = 'TOTE'
Left Join OUOM T11 on T10.UomEntry = T11.UomEntry and T11.UomCode = 'LB'
Left Join OUOM T13 on T12.UomEntry = T13.UomEntry and T13.UomCode = 'GAL'
Left join OITM on T0.UgpCode = OITM.ItemCode
WHERE
OITM.ItemCode = '0000000'
because you are not filtering the result set on #SalesUOM in where clause or inner join.
T10 and T12 are pointing to the same table UGP1.
below are two ways that can resolve your problem
1. Add T11.UomCode = #SalesUOM And T13.UomCode = #SalesUOM in where clause
2. Replace below Statements
"Left Join OUOM T11 on T10.UomEntry = T11.UomEntry and T11.UomCode = 'LB'
Left Join OUOM T13 on T12.UomEntry = T13.UomEntry and T13.UomCode = 'GAL'"
with below statements
Inner Join OUOM T11 on T10.UomEntry = T11.UomEntry and T11.UomCode = #SalesUOM
this Query have one problem with it , except FOR Column
it show multiple values in this coulmn , put as perthe condition it should only show one value '7' , ddepending on this value the coulmn value will be set , but now as it show all the value it cuase too much duplication and other issues
here the query :
SELECT T0.ItemCode, T0.ItemName, T0.CardCode, T0.CodeBars, T0.U_VEN_CODE, T2.UgpCode, T3.AltQty, T3.BaseQty, CASE WHEN T4.Uomentry = - 1 THEN T0.[BuyUnitMsr] ELSE t4.UomName END AS 'UoMName',
T4.UomEntry, T0.U_CAT_CODE, T0.U_CAT_NAME, T1.CardName,
(SELECT TOP (1) PDN1.U_AC_QTY_ORDER
FROM PDN1 INNER JOIN
OPDN ON PDN1.DocEntry = OPDN.DocEntry
WHERE (PDN1.ItemCode = T0.ItemCode) AND (OPDN.CardCode = T0.CardCode)
ORDER BY OPDN.DocDate DESC) AS OQuantity,
(SELECT TOP (1) PDN1_1.U_AC_QTY_BONUS
FROM PDN1 AS PDN1_1 INNER JOIN
OPDN AS OPDN_1 ON PDN1_1.DocEntry = OPDN_1.DocEntry
WHERE (PDN1_1.ItemCode = T0.ItemCode) AND (OPDN_1.CardCode = T0.CardCode)
ORDER BY OPDN_1.DocDate DESC) AS BQuantity, ITM1_1.Price, T0.U_DISC_PER, SMMU01.WhsCode, SMMU01.OnHand, SMAB01.WhsCode AS Expr1, SMAB01.OnHand AS Expr2,
SMKH01.WhsCode AS Expr3, SMKH01.OnHand AS Expr4, ITM9.PriceList, ITM9.Price AS Expr5, ITM1.PriceList AS Expr6, ITM1.Price AS Expr7
FROM OITM AS T0 INNER JOIN
OCRD AS T1 ON T0.CardCode = T1.CardCode INNER JOIN
OUGP AS T2 ON T0.UgpEntry = T2.UgpEntry INNER JOIN
UGP1 AS T3 ON T2.UgpEntry = T3.UgpEntry INNER JOIN
OITW AS SMMU01 ON T0.ItemCode = SMMU01.ItemCode INNER JOIN
OITW AS SMAB01 ON SMMU01.ItemCode = SMAB01.ItemCode INNER JOIN
OITW AS SMKH01 ON SMAB01.ItemCode = SMKH01.ItemCode INNER JOIN
ITM9 ON T0.ItemCode = ITM9.ItemCode AND ITM9.PriceList = '7' INNER JOIN
ITM1 ON T0.ItemCode = ITM1.ItemCode LEFT OUTER JOIN
ITM1 AS ITM1_1 ON T0.ItemCode = ITM1_1.ItemCode AND ITM1_1.PriceList = '10' LEFT OUTER JOIN
OUOM AS T4 ON T3.UomEntry = T4.UomEntry
WHERE (T0.Series = '65') AND (T4.UomEntry = 3 OR
T4.UomEntry = '-1') AND (SMMU01.WhsCode = 'W-SMMU01') AND (SMAB01.WhsCode = 'W-SMAB01') AND (SMKH01.WhsCode = 'W-SMKH01')
and here is the result of the coulmn
Expr6
1
2
3
4
5
6
7
8
9
10
how it possiable to let only shown '7' as decided in the condition ?
thx
SELECT [...]
, ITM1.PriceList AS Expr6
, ITM1.Price AS Expr7
FROM
OITM AS T0
INNER JOIN OCRD AS T1
ON T0.CardCode = T1.CardCode
INNER JOIN OUGP AS T2
ON T0.UgpEntry = T2.UgpEntry
INNER JOIN UGP1 AS T3
ON T2.UgpEntry = T3.UgpEntry
INNER JOIN OITW AS SMMU01
ON T0.ItemCode = SMMU01.ItemCode
INNER JOIN OITW AS SMAB01
ON SMMU01.ItemCode = SMAB01.ItemCode
INNER JOIN OITW AS SMKH01
ON SMAB01.ItemCode = SMKH01.ItemCode
INNER JOIN ITM9
ON T0.ItemCode = ITM9.ItemCode
AND ITM9.PriceList = '7'
INNER JOIN ITM1
ON T0.ItemCode = ITM1.ItemCode
LEFT OUTER JOIN ITM1 AS ITM1_1
ON T0.ItemCode = ITM1_1.ItemCode
AND ITM1_1.PriceList = '10'
LEFT OUTER JOIN OUOM AS T4
ON T3.UomEntry = T4.UomEntry
Your INNER JOIN ITM1 has not PriceList = '7' filter
You should be able to fix it with :
INNER JOIN ITM1
ON T0.ItemCode = ITM1.ItemCode
AND ITM1.PriceList = '7'
The question is now : why ITM1 and ITM9 are duplicated ?
I really appreciate any help with this matter :)
Am Working on a Report now and I had faced some troubles
I have this Query and it work fine , now I want to add a coulmn that is already exist in the query(from the same table) , but this time i'll change the condition of it , BTW the conditions in both of the 2 column are based on one other column
like for example If I have this :
Select Price from ITM1 WHERE PriceList = '1'
and also this
Select Price from ITM1 WHERE PriceList = '10'
how I can write in the same query and let them display in two different column ?
I will put the Query here in case if some one can help me through it :
you can see THE Column Price & PriceList in the lower part of it ,Bolded.
I just need to make the samething again but with a new coulmn name thats it.
Using the IN Operator will give you what you want. However, there are other changes that you can make to your query which would boost performance - but it's out of scope to the question. I'm unclear as to what you're trying to do with the different "columns" Please help explain. Else see #Dave.Gugg's answer which does just that.
SELECT T0.ItemCode,
T0.ItemName,
T0.CardCode,
T0.CodeBars,
T2.UgpCode,
T3.AltQty,
T3.BaseQty,
CASE
WHEN T4.Uomentry = - 1
THEN T0.[BuyUnitMsr]
ELSE t4.UomName
END AS 'UoMName',
T4.UomEntry,
T0.U_CAT_CODE,
T0.U_CAT_NAME,
T1.CardName,
(
SELECT TOP (1) dbo.PDN1.U_AC_QTY_ORDER
FROM dbo.PDN1
INNER JOIN dbo.OPDN ON dbo.PDN1.DocEntry = dbo.OPDN.DocEntry
WHERE (dbo.PDN1.ItemCode = T0.ItemCode)
AND (dbo.OPDN.CardCode = T0.CardCode)
ORDER BY dbo.OPDN.DocDate DESC
) AS OQuantity,
(
SELECT TOP (1) PDN1_1.U_AC_QTY_BONUS
FROM dbo.PDN1 AS PDN1_1
INNER JOIN dbo.OPDN AS OPDN_1 ON PDN1_1.DocEntry = OPDN_1.DocEntry
WHERE (PDN1_1.ItemCode = T0.ItemCode)
AND (OPDN_1.CardCode = T0.CardCode)
ORDER BY OPDN_1.DocDate DESC
) AS BQuantity,
ITM1.Price,
T0.U_DISC_PER
FROM dbo.OITM AS T0
INNER JOIN dbo.OCRD AS T1 ON T0.CardCode = T1.CardCode
INNER JOIN dbo.OUGP AS T2 ON T0.UgpEntry = T2.UgpEntry
INNER JOIN dbo.UGP1 AS T3 ON T2.UgpEntry = T3.UgpEntry
INNER JOIN dbo.ITM1 ON T0.ItemCode = dbo.ITM1.ItemCode
AND dbo.ITM1.PriceList IN ('1', '10')
LEFT JOIN dbo.OUOM AS T4 ON T3.UomEntry = T4.UomEntry
WHERE (T0.Series = '65')
AND (
T4.UomEntry = 3
OR T4.UomEntry = '-1'
)
If you want a different column (this may perform better than two joins):
SELECT T0.ItemCode,
T0.ItemName,
T0.CardCode,
T0.CodeBars,
T2.UgpCode,
T3.AltQty,
T3.BaseQty,
CASE
WHEN T4.Uomentry = - 1
THEN T0.[BuyUnitMsr]
ELSE t4.UomName
END AS 'UoMName',
T4.UomEntry,
T0.U_CAT_CODE,
T0.U_CAT_NAME,
T1.CardName,
(
SELECT TOP (1) dbo.PDN1.U_AC_QTY_ORDER
FROM dbo.PDN1
INNER JOIN dbo.OPDN ON dbo.PDN1.DocEntry = dbo.OPDN.DocEntry
WHERE (dbo.PDN1.ItemCode = T0.ItemCode)
AND (dbo.OPDN.CardCode = T0.CardCode)
ORDER BY dbo.OPDN.DocDate DESC
) AS OQuantity,
(
SELECT TOP (1) PDN1_1.U_AC_QTY_BONUS
FROM dbo.PDN1 AS PDN1_1
INNER JOIN dbo.OPDN AS OPDN_1 ON PDN1_1.DocEntry = OPDN_1.DocEntry
WHERE (PDN1_1.ItemCode = T0.ItemCode)
AND (OPDN_1.CardCode = T0.CardCode)
ORDER BY OPDN_1.DocDate DESC
) AS BQuantity,
CASE
WHEN ITM1.PriceList = '1'
THEN ITM1.Price
ELSE '0'
END AS Price1,
CASE
WHEN ITM1.PriceList = '10'
THEN ITM1.Price
ELSE '0'
END AS Price2,
T0.U_DISC_PER
FROM dbo.OITM AS T0
INNER JOIN dbo.OCRD AS T1 ON T0.CardCode = T1.CardCode
INNER JOIN dbo.OUGP AS T2 ON T0.UgpEntry = T2.UgpEntry
INNER JOIN dbo.UGP1 AS T3 ON T2.UgpEntry = T3.UgpEntry
INNER JOIN dbo.ITM1 ON T0.ItemCode = dbo.ITM1.ItemCode
AND dbo.ITM1.PriceList IN ('1', '10')
LEFT JOIN dbo.OUOM AS T4 ON T3.UomEntry = T4.UomEntry
WHERE (T0.Series = '65')
AND (
T4.UomEntry = 3
OR T4.UomEntry = '-1'
)
You should be able to just join to the table a second time, but you will need to make the joins outer:
SELECT T0.ItemCode ,
T0.ItemName ,
T0.CardCode ,
T0.CodeBars ,
T2.UgpCode ,
T3.AltQty ,
T3.BaseQty ,
CASE WHEN T4.Uomentry = -1 THEN T0.[BuyUnitMsr]
ELSE t4.UomName
END AS 'UoMName' ,
T4.UomEntry ,
T0.U_CAT_CODE ,
T0.U_CAT_NAME ,
T1.CardName ,
( SELECT TOP ( 1 )
dbo.PDN1.U_AC_QTY_ORDER
FROM dbo.PDN1
INNER JOIN dbo.OPDN ON dbo.PDN1.DocEntry = dbo.OPDN.DocEntry
WHERE ( dbo.PDN1.ItemCode = T0.ItemCode )
AND ( dbo.OPDN.CardCode = T0.CardCode )
ORDER BY dbo.OPDN.DocDate DESC
) AS OQuantity ,
( SELECT TOP ( 1 )
PDN1_1.U_AC_QTY_BONUS
FROM dbo.PDN1 AS PDN1_1
INNER JOIN dbo.OPDN AS OPDN_1 ON PDN1_1.DocEntry = OPDN_1.DocEntry
WHERE ( PDN1_1.ItemCode = T0.ItemCode )
AND ( OPDN_1.CardCode = T0.CardCode )
ORDER BY OPDN_1.DocDate DESC
) AS BQuantity ,
dbo.ITM1.Price ,
ITM1Second.Price,
T0.U_DISC_PER
FROM dbo.OITM AS T0
INNER JOIN dbo.OCRD AS T1 ON T0.CardCode = T1.CardCode
INNER JOIN dbo.OUGP AS T2 ON T0.UgpEntry = T2.UgpEntry
INNER JOIN dbo.UGP1 AS T3 ON T2.UgpEntry = T3.UgpEntry
LEFT OUTER JOIN dbo.ITM1 ON T0.ItemCode = dbo.ITM1.ItemCode
AND dbo.ITM1.PriceList = '10'
LEFT OUTER JOIN dbo.ITM1 ITM1Second ON T0.ItemCode = ITM1Second.ItemCode
AND ITM1Second.PriceList = '1'
LEFT OUTER JOIN dbo.OUOM AS T4 ON T3.UomEntry = T4.UomEntry
WHERE ( T0.Series = '65' )
AND ( T4.UomEntry = 3
OR T4.UomEntry = '-1'
)
I am trying to modify a user query in order to return an extra column, INV1.WhsCode from the following SQL query:
SELECT T0.CardCode,
T2.CardName,
T0.CodeBars,
T0.ItemCode,
T0.ItemName,
T3.Price AS [POS Price],
T1.AvgPrice,
T1.OnHand,
T1.MinStock,
T1.MaxStock,
T0.NumInBuy AS Packsize,
T0.LstSalDate,
(
SELECT SUM(Quantity) AS Expr1
FROM dbo.INV1
INNER JOIN OINV
ON INV1.DocEntry = OINV.DocEntry
WHERE INV1.ItemCode = T0.ItemCode
AND INV1.WhsCode = [%2]
AND Month(OINV.DocDate) = month(GetDate())
) AS [Current Period],
(
SELECT SUM(Quantity) AS Expr1
FROM dbo.INV1
INNER JOIN OINV
ON INV1.DocEntry = OINV.DocEntry
WHERE INV1.ItemCode = T0.ItemCode
AND INV1.WhsCode = [%2]
AND Month(OINV.DocDate) = month(GetDate()) - 1
) AS [Previous Period],
(
SELECT SUM(Quantity) AS Expr1
FROM dbo.INV1
INNER JOIN OINV
ON INV1.DocEntry = OINV.DocEntry
WHERE INV1.ItemCode = T0.ItemCode
AND INV1.WhsCode = [%2]
AND Month(OINV.DocDate) = month(GetDate()) - 2
) AS [60-90],
(
SELECT TOP 1 OPDN.DocDate AS Expr1
FROM dbo.PDN1
INNER JOIN OPDN
ON PDN1.DocEntry = OPDN.DocEntry
WHERE PDN1.ItemCode = T0.ItemCode
ORDER BY OPDN.DocDate DESC
) AS LastGRNDate
FROM OITM T0
INNER JOIN OITW T1
ON T0.ItemCode = T1.ItemCode
INNER JOIN OCRD T2
ON T0.CardCode = T2.CardCode
INNER JOIN ITM1 T3
ON T0.ItemCode = T3.ItemCode
INNER JOIN OWHS T4
ON T1.WhsCode = T4.WhsCode
INNER JOIN OITB T5
ON T0.ItmsGrpCod = T5.ItmsGrpCod
WHERE T3.PriceList = '3'
AND T4.WhsName = [%0]
AND T5.ItmsGrpNam = [%1]
How do I achieve this? (MS SQL Server 2008)
There are a number of things wrong/inefficient about your query which I know you didn't ask about, but I am going to answer anyway because it will help answer the question you did ask.
You need to avoid correlated subqueries where possible, there are times that they are unavoidable and the best solution, however I so often see them in a place where a JOIN would do the same job and the optimiser will deal with join so much better. For instance you have:
SELECT (
SELECT TOP 1 OPDN.DocDate AS Expr1
FROM dbo.PDN1
INNER JOIN OPDN
ON PDN1.DocEntry = OPDN.DocEntry
WHERE PDN1.ItemCode = T0.ItemCode
ORDER BY OPDN.DocDate DESC
) AS LastGRNDate
FROM OITM T0
This evaluates the subquery for each row, whereas if you re-wrote as so:
SELECT LastGRN.LastGRNDate
FROM OITM TO
LEFT JOIN
( SELECT PDN1.ItemCode, [LastGRNDate] = MAX(OPDN.DocDate)
FROM dbo.PDN1
INNER JOIN OPDN
ON PDN1.DocEntry = OPDN.DocEntry
GROUP BY PDN1.ItemCode
) LastGRN
ON LastGRN.ItemCode = T0.ItemCode
you would get the same result, but evaluated in a much more efficent manner.
The next fault is your method of using MONTH(GETDATE()) - 1 to get 2 months ago. In January this will evauluate to 0 and get no matches. The best way to do this is to convert each date to the first of each month using something akin to his:
SELECT [FirstOfThisMonth] = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0),
[FirstOfLastMonth] = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE() - 1), 0)
The same principle of joins rather than correlated subqueries can also be applied to your quantity columns, and this gives access to the WhsCode columns, it is not necessary, but I have used a common table expression to clean up the query (using the date logic from above)
WITH Quantities AS
( SELECT [DocMonth] = DATEADD(MONTH, DATEDIFF(MONTH, 0, IONV.DocDate),
Inv1.WhsCode,
ItemCode,
[Quantity] = SUM(Quantity)
FROM dbo.Inv1
INNER JOIN OINV
ON Inv1.DocEntry = OINV.DocEntry
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, IONV.DocDate), WhsCode, itemCode
)
SELECT T0.ItemCode,
[Current Period] = COALESCE(Cur.Quantity, 0),
[Previous Period] = COALESCE(prev.Quantity, 0),
[60-90] = COALESCE(prev2.Quantity, 0)
FROM OITM T0
LEFT JOIN Quantities cur
ON cur.ItemCode = T0.ItemCode
AND cur.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
AND Cur.WhsCode = [%2]
LEFT JOIN Quantities prev
ON prev.ItemCode = T0.ItemCode
AND prev.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 1, 0)
AND prev.WhsCode = [%2]
LEFT JOIN Quantities prev2
ON prev2.ItemCode = T0.ItemCode
AND prev2.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 2, 0)
AND prev2.WhsCode = [%2]
Combining all this into your final query gives:
SELECT T0.CardCode,
T2.CardName,
T0.CodeBars,
T0.ItemCode,
T0.ItemName,
T3.Price,
T1.AvgPrice,
T1.OnHand,
T1.MinStock,
T1.MaxStock,
T0.NumInBuy AS Packsize,
T0.LstSalDate
[Current Period] = COALESCE(Cur.Quantity, 0),
[Previous Period] = COALESCE(prev.Quantity, 0),
[60-90] = COALESCE(prev2.Quantity, 0)
LastGRN.LastGRNDate
FROM OITM T0
INNER JOIN OITW T1
ON T0.ItemCode = T1.ItemCode
INNER JOIN OCRD T2
ON T0.CardCode = T2.CardCode
INNER JOIN ITM1 T3
ON T0.ItemCode = T3.ItemCode
INNER JOIN OWHS T4
ON T1.WhsCode = T4.WhsCode
INNER JOIN OITB T5
ON T0.ItmsGrpCod = T5.ItmsGrpCod
LEFT JOIN Quantities cur
ON cur.ItemCode = T0.ItemCode
AND cur.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
AND Cur.WhsCode = [%2]
LEFT JOIN Quantities prev
ON prev.ItemCode = T0.ItemCode
AND prev.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 1, 0)
AND prev.WhsCode = [%2]
LEFT JOIN Quantities prev2
ON prev2.ItemCode = T0.ItemCode
AND prev2.DocDate = DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP) - 2, 0)
AND prev2.WhsCode = [%2]
LEFT JOIN
( SELECT PDN1.ItemCode, [LastGRNDate] = MAX(OPDN.DocDate)
FROM dbo.PDN1
INNER JOIN OPDN
ON PDN1.DocEntry = OPDN.DocEntry
GROUP BY PDN1.ItemCode
) LastGRN
ON LastGRN.ItemCode = T0.ItemCode
WHERE T3.PriceList = '3'
AND T4.WhsName = [%0]
AND T5.ItmsGrpNam = [%1]
This is all untested so there may be some typos/slight syntax errors, but the same principals should still apply.
If you are still set on the idea of correlated subqueries, you could use APPLY to allow you to access multiple columns from it. e.g.
SELECT T0.Code, cur.WhsCode, cur.Expr1 AS [Current Period]
FROM OITM T0
OUTER APPLY
( SELECT INV1.WhsCode, SUM(Quantity) AS Expr1
FROM dbo.INV1
INNER JOIN OINV
ON INV1.DocEntry = OINV.DocEntry
WHERE INV1.ItemCode = T0.ItemCode
AND INV1.WhsCode = [%2]
AND MONTH(OINV.DocDate) = MONTH(GETDATE())
) cur
All your subqueries contain in the where clause the following: INV1.WhsCode = [%2]
That means instead of INV1.WhsCode you can just return [%2] like this:
SELECT [%2] as WhsCode,
T0.CardCode,
T2.CardName,
T0.CodeBars,
......
This assumes that [%2] and the other similar tokens get replaced by the app with something SQL Server understands, before this gets send to get executed.