sqldb2jdedwards

Complicated SQL query help for JD Edwards E1 (DB2)


Let me preface this with the admission that I am not a database or SQL expert by any stretch. I know basic queries and have done some slightly more involved queries, but this is beyond my ken.

Background

My company uses JD Edwards Enterprise One for their ERP application. The tables below are represented by actual tables in this system. I have paraphrased them below for simplicity. The back-end database is DB2 running on an AS/400 platform.

Table Definitions

Table: Item Ledger (IL)
Columns:

Business Unit
Work Center
Order #
Doc Type
Trans. Date
Qty Completed

Table: W/O Time Transactions (WOT)
Columns:

Business Unit
Work Center
Order #
Hours Type
G/L Date
Hours Worked

Notes:

Sample Data

Note: Apologies for the poor formatting, but there seems to be no way to represent a table nicely in this venue.

Item Ledger (IL)

Business Unit   Work Center Order # Doc Type    Trans. Date Qty Completed
BU-1    WC-1    1   IC  8/7/20  20
BU-1    WC-1    1   IC  8/7/20  40
BU-1    WC-1    2   IC  8/7/20  10
BU-1    WC-2    3   IC  8/7/20  40
BU-1    WC-2    3   IC  8/7/20  10
BU-2    WC-4    6   IC  8/7/20  10
BU-2    WC-5    5   IC  8/7/20  60
BU-1    WC-1    2   IC  8/6/20  50
BU-1    WC-3    4   IC  8/6/20  30
BU-2    WC-5    5   IC  8/5/20  50
BU-2    WC-5    7   IC  8/1/20  20
BU-2    WC-5    8   IC  7/26/20 30
BU-2    WC-5    8   IC  7/25/20 50

W/O Time Transactions (WOT)

Business Unit   Work Center Order # Hours Type  G/L Date    Hours Worked
BU-2    WC-4    6   3   8/8/20  7.4
BU-1    WC-1    1   3   8/7/20  3.92
BU-1    WC-2    3   3   8/7/20  8
BU-1    WC-2    3   3   8/7/20  7
BU-1    WC-3    4   3   8/7/20  6.2
BU-2    WC-4    6   3   8/7/20  1.1
BU-1    WC-1    2   3   8/6/20  1.57
BU-2    WC-5    7   3   8/1/20  3.9
BU-2    WC-5    8   3   7/25/20 11.3

Note: No entries for order # 5 in the time transactions table.

Goals

Goal 1:

We are trying to get hours worked and quantities completed, grouped by business unit (e.g. BU-1) and work center (e.g. WC-1), totaled by the week (future: add other time ranges like by the month).

Important things to note are that there may be multiple completions on a given day in the item ledger, and there may be a much smaller (sometimes just one) number of entries in the time transactions for hours worked that correspond to those completions. There are also often situations where the hours worked entry may not be posted until the next day (this is a 24x7 operation with shifts), in which case the related events (completion and hours logging for a given order) are on separate days.

If we were to meld together the data from these two tables, where order number is the common tie:

Note: I assembled this manually, so there could be errors.

Business Unit   Work Center Order # Date    Hours Worked    Qty Completed
BU-2    WC-4    6   8/8/20  7.4 null
BU-1    WC-1    1   8/7/20  3.92    60
BU-1    WC-1    2   8/7/20  null    10
BU-1    WC-2    3   8/7/20  15  50
BU-1    WC-3    4   8/7/20  6.2 null
BU-2    WC-4    6   8/7/20  1.1 10
BU-2    WC-5    5   8/7/20  null    60
BU-1    WC-1    2   8/6/20  1.57    50
BU-1    WC-3    4   8/6/20  null    30
BU-2    WC-5    5   8/5/20  null    50
BU-2    WC-5    7   8/1/20  3.9 20
BU-2    WC-5    8   7/26/20 null    30
BU-2    WC-5    8   7/25/20 11.3    50

Now, grouped by business unit, work center and totaled by the week:

Week    Business Unit   Work Center Hours Worked    Qty Completed
8/2/20 – 8/8/20             
    BU-2    WC-4    8.5 10
    BU-1    WC-1    5.49    120
    BU-1    WC-2    15  50
    BU-1    WC-3    6.2 30
    BU-2    WC-5    0   50
7/26/20 – 8/1/20                
    BU-2    WC-5    3.9 50
7/19/20 – 7/25/20               
    BU-2    WC-5    11.3    50

I do not know the proper SQL query to achieve this result. I thought that this would require a full outer join, but everything I have tried seems to result in some sort of Cartesian product for a result set, and this is just the first step of combining the data from the two tables together, never mind the final aggregation and grouping.

Any help and suggestions on how to write a query (or maybe multiple queries?) to achieve this type of result would be very much appreciated.

Update (8/14/20):

I have tried to implement a query based on https://stackoverflow.com/users/10418264/mark-barinstein (Mark Barinstein) suggestions. I've analyzed the suggested query and I think I understand it for the most part.

I'm struggling with getting the JD Edwards Julian date into a form that can be used to calculate the week of the year. Here is may latest attempt. Note that the actual table and column names are in use here.

SELECT
  COALESCE(ILG.Week, WOG.Week) AS WEEK,
  COALESCE(ILG.BU, WOG.BU) AS BU,
  COALESCE(ILG.WC, WOG.WC) AS WC,
  COALESCE(WOG.Hours, 0) AS HOURS,
  COALESCE(ILG.Qty, 0) AS QTY
FROM
  (
    SELECT
      F31122.WTMMCU AS BU,
      F31122.WTMCU AS WC,
      WEEK(DATE(CAST(1900 + F31122.WTDGL/1000 AS CHAR(4)) || '-01-01') + (MOD(F31122.WTDGL, 1000) - 1) DAYS) AS Week,
      SUM(F31122.WTHRW) AS Hours
    FROM PROD2DTA.F31122 AS F31122
    WHERE
      (F31122.WTTYR IN ('3')) AND
      (F31122.WTDGL BETWEEN 120200 AND 120201)
    GROUP BY
      F31122.WTMMCU,
      F31122.WTMCU
  ) WOG
FULL JOIN
  (
    SELECT
      F4111.ILMCU AS BU,
      F4111.ILLOCN AS WC,
      WEEK(DATE(CAST(1900 + F4111.ILTRDJ/1000 AS CHAR(4)) || '-01-01') + (MOD(F4111.ILTRDJ, 1000) - 1) DAYS) AS Week,
      SUM(F4111.ILTRQT) AS Qty
    FROM PROD2DTA.F4111 AS F4111
    WHERE
      (F4111.ILDCT IN ('IC')) AND
      (F4111.ILTRDJ BETWEEN 120200 AND 120201)
    GROUP BY
      F4111.ILMCU,
      F4111.ILLOCN
  ) ILG
ON ILG.BU = WOG.BU AND ILG.WC = WOG.WC AND ILG.WEEK = WOG.WEEK
ORDER BY 1 DESC, 2, 3

Is there a way to simplify the logic that converts the JDE Julian date to a week number? I understand what's being done, but wish I could break it out as a function and call it.

I'm still getting errors though:

[SQL0122] Column WTDGL or expression in SELECT list not valid. (JdbcException)

Different question: Can the column "alias" (e.g. BU instead of F4111.ILMCU) be used in the GROUP BY clause? It would make it much more readable.


Solution

  • Try this:

    SELECT
      COALESCE(ILG.WEEK, WOG.WEEK) AS WEEK
    , COALESCE(ILG.BU, WOG.BU) AS BU
    , COALESCE(ILG.WC, WOG.WC) AS WC
    , COALESCE(WOG.Hours, 0) AS HOURS
    , COALESCE(ILG.Qty, 0) AS QTY
    FROM
    (
    SELECT BU, WC, WEEK(TO_DATE(GL_Date, 'MM/DD/YY')) AS Week, SUM(Hours) AS Hours
    FROM WO
    GROUP BY BU, WC, WEEK(TO_DATE(GL_Date, 'MM/DD/YY'))
    ) WOG
    FULL JOIN
    (
    SELECT 
      BU, WC
    , WEEK(TO_DATE(Trans_Date, 'MM/DD/YY')) AS Week
    , SUM(Qty) AS Qty
    FROM IL
    GROUP BY BU, WC, WEEK(TO_DATE(Trans_Date, 'MM/DD/YY'))
    ) ILG ON ILG.BU = WOG.BU AND ILG.WC = WOG.WC AND ILG.WEEK = WOG.WEEK
    ORDER BY 1 DESC, 2, 3
    

    db<>fiddle link to test it.