Hi all
I was interested in SqlSister's response to a question in which she stated that a derived table would allow returning more than one result whereas a correlated subquery precludes this (I presume unless the subquery is the data for an IN / NOT IN clause ?)
I have a query of items in an item table that has to report on several different stock-holding and sales data aggregates; I was using correlated subqueries because I can't create views and am not sure if a view would help in any case. One subquery has to return several pieces of data from the sales history table and so I strung them together in order to break them down into separate columns when the results are exported to excel.
Would a derived table serve me better, and can I make use of one?
I'm using MS Query from Office 2003 on an SQL Server 2000 installation (running on Windows Server 2003 I believe).
My problem subquery is [blue]highlighted[/blue] in the code below ... if any other parts can be tweeaked / optimised then please don't hold back; let me know!
[code:]
SELECT
InvMaster.StockCode AS 'StockCode', -- from Inventory Master file
InvMaster.ProductClass AS 'PrdClass',
SalProdClass.Description AS 'PrdClassDescription', -- from SalesAnalysis ProductClass file
InvMaster.Description AS 'Desc',
InvMaster.LongDesc AS 'ExtraDescription',
InvMaster.AlternateKey1 AS 'PackSize', -- userdefined field used to denote an items packsize, e.g compliment slips are in packs of 50, 1 unit = pack of 50
InvWarehouse.QtyOnHand AS 'InStock', -- from Inventory Warehouse file; each client's stock is held under different warehouse codes
Max(InvFifoLifo.LastReceiptDate) AS 'LastReceipt',
HaveStock =
CASE InvWarehouse.QtyOnHand
WHEN 0 THEN 0
ELSE 1
END, -- allows the summation of whether or not the item is in stock (to be used as a SUM in a pivot table for a count function)
OnWeb =
CASE AFDWeb.AlphaValue -- customform data item (criteria in where clause) from table AdmFormData which is a table used again as a nested select...
WHEN 'Y' THEN 'Yes'
WHEN 'N' THEN 'No'
ELSE '???'
END, -- allows the summation of whether or not the item is visible to client on the web (to be used as a SUM in a pivot table for a count function)
/* HERE BEGINS MY SERIES OF NESTED SELECTS - I APPRECIATE THESE MAY BE BETTER SERVED AS VIEWS (OR EVEN SPs) but I can't create views with my level of access
**
** 1st nested select (correlated subquery?) to return a count of bin locations which are pallet-spaces (others are pick-faces)
**
** Uses InvMaster.StockCode as the code for which to obtain the number of the appropriate bin locations where stock is present for that client
**
*/
(
SELECT
count(InvMultBin.Bin)
FROM
SysproCompanyH.dbo.InvMultBin InvMultBin
WHERE
InvMultBin.StockCode = InvMaster.StockCode
AND InvMultBin.Bin like 'F%'
AND InvMultBin.QtyOnHand1 >$0
) AS 'PalletCount',
/* 2nd nested select returns a subdivision of the ProductClass, and combines this with the client-owner
** (client owner of a subdivision, or of ProductClass where there is no subdivision)
**
** Product Class "subdivision" and "client owner" are new data items introduced by the client.
** Our dba advised there were no remaining fields available to link this to existing productclass data
** we had to use the CustomFormField capability of the Syspro system to introduce two extra fields (per stock item in InvMaster)
** these extra fields are stored in the AdmFormData table whose Keyfield is linked to the InvMaster.StockCode field
**
** this portion uses the AdmFormData table and links to itself as an alias to pik up both fields in the same pass
** both fields are then concatenated into one returned value passed back to the main query
*/
(
SELECT
(RTRIM(AFD.AlphaValue)+' : '+RTRIM(AFD_1.AlphaValue))
FROM
SysproCompanyH.dbo.AdmFormData AFD
INNER JOIN SysproCompanyH.dbo.AdmFormData AFD_1
ON AFD.KeyField = AFD_1.KeyField
AND AFD.FormType = AFD_1.FormType
WHERE
(
(AFD.KeyField = InvMaster.StockCode)
AND (AFD.FieldName='SubDiv')
AND (AFD_1.FieldName='Owner')
)
) AS 'PC-Ctg-Owner',
-- 3rd nested select to return the 12wkusage of the stock item, taken from the InvMovements table
(
SELECT
SUM(TrnQty)
FROM
SysproCompanyH.dbo.InvMovements InvMovements
WHERE
InvMovements.StockCode = InvMaster.StockCode
AND (MovementType = 'S')
AND (EntryDate >= DATEADD([DAY], - 83, { fn CURDATE() }))
AND (EntryDate <= DATEADD([DAY], 0, { fn CURDATE() }))
) As 'Usage12Wks',
[blue]
/* HELP REQUIRED HERE
** 4th nested select to return different elements of sales order throughput for the last 7 days
** Because nested selects (correlated subqueries) can only return one value I've had to string the values together
** and when the results are returned to excel I extrapolate the values based on the position of the changing delimiters
** delimiters are , ; : #
*/
(
SELECT
RTRIM(LTRIM(STR(SUM(SorDetail.MOrderQty))))+ ',' +
RTRIM(LTRIM(STR(SUM(SorDetail.MBackOrderQty)))) + ';' +
RTRIM(LTRIM(STR(SUM(SorDetail.MQtyDispatched)))) + ':' +
RTRIM(LTRIM(STR(SUM(SorDetail.MShipQty)))) + '#' +
RTRIM(LTRIM(STR(SUM(SorDetail.MStockQtyToShp))))
FROM
SysproCompanyH.dbo.SorDetail SorDetail
INNER JOIN SysproCompanyH.dbo.SorMaster SorMaster
ON SorDetail.SalesOrder = SorMaster.SalesOrder
AND SorMaster.Warehouse = 'BC'
WHERE
SorDetail.MStockCode = InvMaster.StockCode
AND SorMaster.Warehouse = 'BC'
AND SorMaster.OrderStatus NOT IN ('*', '\') -- these are cancelled-order statuses
AND SorDetail.MProductClass <> '_FRT'
AND (DATEDIFF(DAY, SorMaster.OrderDate, GETDATE()) BETWEEN 7 AND 13)
/*
** I'll refine this later so that it always configures the date range to be from the previous Monday to the previous Sunday's dates.
*/
) As 'Last7Days'
[/blue]
FROM
SysproCompanyH.dbo.InvMaster InvMaster
INNER JOIN SysproCompanyH.dbo.InvWarehouse InvWarehouse
ON InvMaster.StockCode = InvWarehouse.StockCode
INNER JOIN SysproCompanyH.dbo.SalProductClassDes SalProdClass
ON InvMaster.ProductClass = SalProdClass.ProductClass
LEFT OUTER JOIN SysproCompanyH.dbo.AdmFormData AFDWeb
ON InvMaster.StockCode = AFDWeb.KeyField
AND AFDWeb.FieldName = 'WEBRQD'
LEFT OUTER JOIN SysproCompanyH.dbo.InvFifoLifo InvFifoLifo
ON InvWarehouse.StockCode = InvFifoLifo.StockCode
AND InvWarehouse.Warehouse = InvFifoLifo.Warehouse
WHERE
InvWarehouse.Warehouse='BC'
GROUP BY
InvMaster.StockCode,
InvMaster.Description,
InvMaster.LongDesc,
InvMaster.AlternateKey1,
InvMaster.ProductClass,
SalProdClass.Description,
InvWarehouse.QtyOnHand,
AFDWeb.AlphaValue
ORDER BY
InvMaster.StockCode
[/code]
Mark, HH Associates
I was interested in SqlSister's response to a question in which she stated that a derived table would allow returning more than one result whereas a correlated subquery precludes this (I presume unless the subquery is the data for an IN / NOT IN clause ?)
I have a query of items in an item table that has to report on several different stock-holding and sales data aggregates; I was using correlated subqueries because I can't create views and am not sure if a view would help in any case. One subquery has to return several pieces of data from the sales history table and so I strung them together in order to break them down into separate columns when the results are exported to excel.
Would a derived table serve me better, and can I make use of one?
I'm using MS Query from Office 2003 on an SQL Server 2000 installation (running on Windows Server 2003 I believe).
My problem subquery is [blue]highlighted[/blue] in the code below ... if any other parts can be tweeaked / optimised then please don't hold back; let me know!
[code:]
SELECT
InvMaster.StockCode AS 'StockCode', -- from Inventory Master file
InvMaster.ProductClass AS 'PrdClass',
SalProdClass.Description AS 'PrdClassDescription', -- from SalesAnalysis ProductClass file
InvMaster.Description AS 'Desc',
InvMaster.LongDesc AS 'ExtraDescription',
InvMaster.AlternateKey1 AS 'PackSize', -- userdefined field used to denote an items packsize, e.g compliment slips are in packs of 50, 1 unit = pack of 50
InvWarehouse.QtyOnHand AS 'InStock', -- from Inventory Warehouse file; each client's stock is held under different warehouse codes
Max(InvFifoLifo.LastReceiptDate) AS 'LastReceipt',
HaveStock =
CASE InvWarehouse.QtyOnHand
WHEN 0 THEN 0
ELSE 1
END, -- allows the summation of whether or not the item is in stock (to be used as a SUM in a pivot table for a count function)
OnWeb =
CASE AFDWeb.AlphaValue -- customform data item (criteria in where clause) from table AdmFormData which is a table used again as a nested select...
WHEN 'Y' THEN 'Yes'
WHEN 'N' THEN 'No'
ELSE '???'
END, -- allows the summation of whether or not the item is visible to client on the web (to be used as a SUM in a pivot table for a count function)
/* HERE BEGINS MY SERIES OF NESTED SELECTS - I APPRECIATE THESE MAY BE BETTER SERVED AS VIEWS (OR EVEN SPs) but I can't create views with my level of access
**
** 1st nested select (correlated subquery?) to return a count of bin locations which are pallet-spaces (others are pick-faces)
**
** Uses InvMaster.StockCode as the code for which to obtain the number of the appropriate bin locations where stock is present for that client
**
*/
(
SELECT
count(InvMultBin.Bin)
FROM
SysproCompanyH.dbo.InvMultBin InvMultBin
WHERE
InvMultBin.StockCode = InvMaster.StockCode
AND InvMultBin.Bin like 'F%'
AND InvMultBin.QtyOnHand1 >$0
) AS 'PalletCount',
/* 2nd nested select returns a subdivision of the ProductClass, and combines this with the client-owner
** (client owner of a subdivision, or of ProductClass where there is no subdivision)
**
** Product Class "subdivision" and "client owner" are new data items introduced by the client.
** Our dba advised there were no remaining fields available to link this to existing productclass data
** we had to use the CustomFormField capability of the Syspro system to introduce two extra fields (per stock item in InvMaster)
** these extra fields are stored in the AdmFormData table whose Keyfield is linked to the InvMaster.StockCode field
**
** this portion uses the AdmFormData table and links to itself as an alias to pik up both fields in the same pass
** both fields are then concatenated into one returned value passed back to the main query
*/
(
SELECT
(RTRIM(AFD.AlphaValue)+' : '+RTRIM(AFD_1.AlphaValue))
FROM
SysproCompanyH.dbo.AdmFormData AFD
INNER JOIN SysproCompanyH.dbo.AdmFormData AFD_1
ON AFD.KeyField = AFD_1.KeyField
AND AFD.FormType = AFD_1.FormType
WHERE
(
(AFD.KeyField = InvMaster.StockCode)
AND (AFD.FieldName='SubDiv')
AND (AFD_1.FieldName='Owner')
)
) AS 'PC-Ctg-Owner',
-- 3rd nested select to return the 12wkusage of the stock item, taken from the InvMovements table
(
SELECT
SUM(TrnQty)
FROM
SysproCompanyH.dbo.InvMovements InvMovements
WHERE
InvMovements.StockCode = InvMaster.StockCode
AND (MovementType = 'S')
AND (EntryDate >= DATEADD([DAY], - 83, { fn CURDATE() }))
AND (EntryDate <= DATEADD([DAY], 0, { fn CURDATE() }))
) As 'Usage12Wks',
[blue]
/* HELP REQUIRED HERE
** 4th nested select to return different elements of sales order throughput for the last 7 days
** Because nested selects (correlated subqueries) can only return one value I've had to string the values together
** and when the results are returned to excel I extrapolate the values based on the position of the changing delimiters
** delimiters are , ; : #
*/
(
SELECT
RTRIM(LTRIM(STR(SUM(SorDetail.MOrderQty))))+ ',' +
RTRIM(LTRIM(STR(SUM(SorDetail.MBackOrderQty)))) + ';' +
RTRIM(LTRIM(STR(SUM(SorDetail.MQtyDispatched)))) + ':' +
RTRIM(LTRIM(STR(SUM(SorDetail.MShipQty)))) + '#' +
RTRIM(LTRIM(STR(SUM(SorDetail.MStockQtyToShp))))
FROM
SysproCompanyH.dbo.SorDetail SorDetail
INNER JOIN SysproCompanyH.dbo.SorMaster SorMaster
ON SorDetail.SalesOrder = SorMaster.SalesOrder
AND SorMaster.Warehouse = 'BC'
WHERE
SorDetail.MStockCode = InvMaster.StockCode
AND SorMaster.Warehouse = 'BC'
AND SorMaster.OrderStatus NOT IN ('*', '\') -- these are cancelled-order statuses
AND SorDetail.MProductClass <> '_FRT'
AND (DATEDIFF(DAY, SorMaster.OrderDate, GETDATE()) BETWEEN 7 AND 13)
/*
** I'll refine this later so that it always configures the date range to be from the previous Monday to the previous Sunday's dates.
*/
) As 'Last7Days'
[/blue]
FROM
SysproCompanyH.dbo.InvMaster InvMaster
INNER JOIN SysproCompanyH.dbo.InvWarehouse InvWarehouse
ON InvMaster.StockCode = InvWarehouse.StockCode
INNER JOIN SysproCompanyH.dbo.SalProductClassDes SalProdClass
ON InvMaster.ProductClass = SalProdClass.ProductClass
LEFT OUTER JOIN SysproCompanyH.dbo.AdmFormData AFDWeb
ON InvMaster.StockCode = AFDWeb.KeyField
AND AFDWeb.FieldName = 'WEBRQD'
LEFT OUTER JOIN SysproCompanyH.dbo.InvFifoLifo InvFifoLifo
ON InvWarehouse.StockCode = InvFifoLifo.StockCode
AND InvWarehouse.Warehouse = InvFifoLifo.Warehouse
WHERE
InvWarehouse.Warehouse='BC'
GROUP BY
InvMaster.StockCode,
InvMaster.Description,
InvMaster.LongDesc,
InvMaster.AlternateKey1,
InvMaster.ProductClass,
SalProdClass.Description,
InvWarehouse.QtyOnHand,
AFDWeb.AlphaValue
ORDER BY
InvMaster.StockCode
[/code]
Mark, HH Associates