Вопрос

My task is to convert stored procedure from SQL Server to Progress code.

Everything is going well but I faced a mystery yesterday.

How can we do aggregate function like Min, Max, Avg, etc. in Progress OpenEdge V10.2B?

Here a SQL Server scenario:

WITH Inventory (ItemNo, Quantity)
AS
(
          SELECT 'ItemA', 100
    UNION SELECT 'ItemA', 200
    UNION SELECT 'ItemC', 300
    UNION SELECT 'ItemB', 400
    UNION SELECT 'ItemA', 500
    UNION SELECT 'ItemB', 600
)
SELECT
    ItemNo
    ,MIN(Quantity)   AS Min1
    ,MAX(Quantity)   AS Max1
    ,AVG(Quantity)   AS Avg1
    ,SUM(Quantity)   AS Sum1
    ,COUNT(Quantity) AS Count1
FROM Inventory
GROUP BY
    ItemNo

The result is:

ItemNo   Min1    Max1    Avg1    Sum1     Count1
ItemA    100     500     266     800      3
ItemB    400     600     500     1000     2
ItemC    300     300     300     300      1

Thank you, Have a great day! Sebastien

Это было полезно?

Решение

OK, I like a challenge. So, here's the solution using the built-in aggregation functions of Progress.

First, some housekeeping: setting up the temp-table and filling it:

DEFINE TEMP-TABLE ttTest
    FIELD ItemNo AS CHARACTER
    FIELD Quantity AS INTEGER
    INDEX ItemNo ItemNo.

RUN ipCreateTest("ItemA",100).
RUN ipCreateTest("ItemA",200).
RUN ipCreateTest("ItemC",300).
RUN ipCreateTest("ItemB",400).
RUN ipCreateTest("ItemA",500).
RUN ipCreateTest("ItemB",600).

PROCEDURE ipCreateTest:
DEFINE INPUT  PARAMETER pcItem AS CHARACTER   NO-UNDO.
DEFINE INPUT  PARAMETER piQty  AS INTEGER     NO-UNDO.

CREATE ttTest.
ASSIGN
    ttTest.ItemNo = pcItem
    ttTest.Quantity = piQty
    .
END.

Then, the actual reporting part:

FOR EACH ttTest
    NO-LOCK
    BREAK BY ttTest.ItemNo:
    ACCUMULATE ttTest.Quantity
        (MINIMUM MAXIMUM AVERAGE TOTAL COUNT BY ttTest.Itemno).
    IF LAST-OF(ttTest.itemNo) THEN DO:
        DISPLAY
            ttTest.ItemNo
            ACCUM MINIMUM BY ttTest.ItemNo ttTest.Quantity
                COLUMN-LABEL "Min1"
            ACCUM MAXIMUM BY ttTest.ItemNo ttTest.Quantity
                COLUMN-LABEL "Max1"
            ACCUM AVERAGE BY ttTest.ItemNo ttTest.Quantity
                COLUMN-LABEL "Avg1"
            ACCUM TOTAL BY ttTest.ItemNo ttTest.Quantity
                COLUMN-LABEL "Sum1"
            ACCUM COUNT BY ttTest.ItemNo ttTest.Quantity
                COLUMN-LABEL "Count1"
            .
    END.
END.

The built-in functions work, but the syntax is very counter-intuitive IMHO. I would go with Tim's solution, mainly because I probably would have finished the problem with that strategy in the time it took me to get to the second iteration with ACCUM and ACCUMULATE, figuring out where the brackets go... :)

Другие советы

This will get you the values you're looking for by ItemNo:

    DEFINE VARIABLE iMin    AS INTEGER      NO-UNDO.
    DEFINE VARIABLE iMax    AS INTEGER      NO-UNDO.
    DEFINE VARIABLE iTotal  AS INTEGER      NO-UNDO.
    DEFINE VARIABLE iCount  AS INTEGER      NO-UNDO.


    FOR EACH Inventory
        NO-LOCK
        BREAK BY Inventory.itemno
        :

        IF FIRST-OF(Inventory.itemno) THEN
            ASSIGN
                iMin    = 99999999
                iMax    = -99999999
                iTotal  = 0
                iCount  = 0
                .

        ASSIGN
            iMin    = MIN(iMin, inventory.quantity)
            iMax    = MAX(iMax, inventory.quantity)
            iTotal  = iTotal + inventory.quantity 
            iCount  = iCount + 1
            .

        IF LAST-OF(Inventory.itemno) THEN
            DISPLAY
                    Inventory.itemno
                    iMin
                    iMax
                    iTotal / iCount
                    iTotal
                    iCount
                WITH FRAME f-show
                    DOWN
                    .

    END.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top