Quantcast
Viewing all articles
Browse latest Browse all 8

Reqursive Queries in Production / Sales Analysis

In last few months I have found several questions on the SAP Business One forums - SQL Queries about  Bill of Materails. In this blog i would like to demonstrate a features of MS SQL 2005 Common Table Expressions used as recursive queries.

Common use of recursive queries: Returning hierarchical data like
- displaying data in a bill of materials (BOM) in Production or Sales module
- displaying sales document flow from Sales Order to Credit Memo

Recursive CTE

Recursive CTE structure must contain one Ancor and Recusrive Member.The anchor member(s) creating the first invocation or base result set (T0), then the recursive member(s) using the base or previous result set (Ti) as input to gerenare the next result set (Ti+1) as output. The process gies until an empty result set. The results joined by UNION ALL operators. The depth of the recursion can be managed by OPTION (MAXRECURSION [i])

Syntax:

WITH cte_name ( column_name [,...n] ) 
AS 
(   CTE_query_definition –- Anchor member is defined. 
 UNION ALL   CTE_query_definition –- Recursive member is defined referencing cte_name. 
) 

-- Statement using the CTE 
SELECT * FROM cte_name 

Expanding a Product Tree

Product Tree defintion is stored at OITT and ITT1 tables. The following Query will expand the product tree:

WITH BOM (Code, Level, TreeType) AS
(
 SELECT    T0.Code, 0 as Level, T2.TreeType  FROM    dbo.OITT T0 inner join OITM T2 on T0.Code = T2.ItemCode  WHERE         T0.Code =  'PRODUCT_CODE'
UNION ALL  SELECT         T1.Code , Level +1 , T2.TreeType   FROM             dbo.ITT1 AS T1 inner join OITM T2 on T1.Code = T2.ItemCode    JOIN BOM ON T1.Father = BOM.Code
)

SELECT * FROM BOM OPTION (MAXRECURSION 99)

List of Transaction related to a Product Tree

List of Transactions of one Product can be determined by easily with recursively. The Issue for Production and Receipt from Production documents are linked to warehouse journal (table OINM) by the fields ApplObj, AppObjType, AppObjAbs.

The list the transactions of a production order  related to one product from Warehouse Journal can be received by the following query (continue example of expanding product tree):

SELECT   T0.TransType,T1.DocNum, T0.ItemCode, T0.InQty, T0.OutQty,   T0.TransValue, T0.AppObjType,T2.Level
FROM   OINM T0 INNER JOIN OWOR T1 ON T0.AppObjAbs = T1.DocEntry   INNER JOIN BOM T2 ON T0.ItemCode = T2.Code
WHERE   T0.ApplObj = '202'      

COGS of Sales BOM

Cost price of multi level Sales BOM also easy to determine based on product tree query:

SELECT   T0.TransType, T0.Base_Ref,  sum( T0.TransValue)
FROM      oinm T0 INNER JOIN BOM T1 ON T0.ItemCode = T1.Code
GROUP BY      T0.TransType, T0.Base_Ref          

Sales Document Flow

In SAP B1 the sales documents can be linked together by Copy To - Copy From function on the forms. In the document tables the BaseLine, BaseType, BaseEntry fields of the target document define these relations to LineNum, ObjType and DocEntry fields of the source document. To handle a view - wich contains there (and necessary) informations - is easier than use tables indivudailly to make analisys on the sales process.

CREATE VIEW CTE_sales
AS
SELECT   '1.ORDER' [Level],T0.DocEntry,T0.DocNum,T0.DocDate,T0.ObjType,  T0.CardCode,T1.LineNum,T1.ItemCode,T1.Quantity,T1.BaseType,  T1.BaseRef,T1.BaseEntry,T1.BaseLine 
FROM   ORDR T0 INNER JOIN RDR1 T1 ON T0.DocEntry = T1.DocEntry
UNION ALL  SELECT   '2.DELIVERY' [Level],T0.DocEntry,T0.DocNum,T0.DocDate,T0.ObjType,  T0.CardCode,T1.LineNum,T1.ItemCode,T1.Quantity,T1.BaseType,  T1.BaseRef,T1.BaseEntry,T1.BaseLine 
FROM   ODLN T0 INNER JOIN DLN1 T1 ON T0.DocEntry = T1.DocEntry
UNION ALL
SELECT  '3.RETURN' [Level],T0.DocEntry,T0.DocNum,T0.DocDate,T0.ObjType,  T0.CardCode,T1.LineNum,T1.ItemCode,T1.Quantity,T1.BaseType,  T1.BaseRef,T1.BaseEntry,T1.BaseLine 
FROM   ORDN T0 INNER JOIN RDN1 T1 ON T0.DocEntry = T1.DocEntry
UNION ALL
SELECT   '4.INVOICE' [Level],T0.DocEntry,T0.DocNum,T0.DocDate,T0.ObjType,  T0.CardCode,T1.LineNum,T1.ItemCode,T1.Quantity, T1.BaseType,  T1.BaseRef,T1.BaseEntry,T1.BaseLine 
FROM   OINV T0 INNER JOIN INV1 T1 ON T0.DocEntry = T1.DocEntry
UNION ALL
SELECT   '5.CREDIT MEMO' [Level],T0.DocEntry,T0.DocNum,T0.DocDate,T0.ObjType,  T0.CardCode,T1.LineNum,T1.ItemCode,T1.Quantity, T1.BaseType,  T1.BaseRef,T1.BaseEntry,T1.BaseLine 
FROM   ORIN T0 INNER JOIN RIN1 T1 ON T0.DocEntry = T1.DocEntry          

Use the following recursive query based on CTE_sales view to track a sales order:

WITH sales( [Level],CardCode,DocEntry,DocNum,DocDate,ObjType,LineNum,   ItemCode,Quantity, BaseEntry, BaseLine, BaseType) AS
(  SELECT     T0.[Level],T0.CardCode,T0.DocEntry, T0.DocNum,T0.DocDate,T0.ObjType,    T0.LineNum,T0.ItemCode,T0.Quantity,T0.BaseEntry,T0.BaseLine,T0.BaseType  FROM     CTE_sales T0  WHERE     T0.ObjType = '17' AND T0.DocNum = 'SALES_ORDER_NUMBER'
UNION ALL  SELECT     T0.[Level], T0.CardCode,T0.DocEntry,T0.DocNum,T0.DocDate,T0.ObjType,    T0.LineNum,T0.ItemCode,T0.Quantity,T0.BaseEntry,T0.BaseLine,T0.BaseType  FROM     CTE_sales T0 INNER JOIN sales T1 ON T1.DocEntry= T0.BASeEntry     AND T1.ObjType = T0.BaseType AND T1.LineNum = T0.BaseLine
)

SELECT * FROM sales ORDER BY [Level]

Of course there examples can be migrated to a stored procedures or can be run from SAP B1 application with paramters.

Conclusion

A recursive CTE can greatly simplify, easy to use to display hierarchical data production or sales analisys.


Viewing all articles
Browse latest Browse all 8

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>