Home > Net >  Best way to join line items on sales order
Best way to join line items on sales order

Time:12-09

I have what is probably a remedial question, but I am struggling to come up with the best way to implement it through searching. I am working on a retool workflow that will get the latest shipped sales orders, and send an email. The database I am querying has a Sales Order -> Line Items relationship.

Simplified Example: SalesOrderTable

SalesOrderID Customer SoldDate ShipDate
1 Customer1 12/7/22 12/7/22
2 Customer1 12/7/22 12/7/22
3 Customer2 12/7/22 12/7/22

Lines on the sales orders

LineItemID LineNumber SalesOrderID Product Price
1 1 1 Eggs $1.00
2 2 1 Milk $1.00
3 1 2 Bread $1.00
4 2 2 Eggs $1.00
5 3 2 Milk $1.00
6 1 3 Eggs $1.00

I am unsure the best way to join the lines to the sales orders. Obviously simply joining the data isn't really what I want, I don't think. Meaning

SELECT * FROM SalesOrder
JOIN lines ON SalesOrder.SalesOrderID = Lines.SalesOrderID
WHERE SalesOrderID = 2

Would produce something like(don't think this is the right way to accomplish):

SalesOrderID Customer SoldDate ShipDate LineItemID LineNumber SalesOrderID Product Price
2 Customer2 12/7/22 12/7/22 3 1 2 Bread $1.00
2 Customer2 12/7/22 12/7/22 4 2 2 Eggs $1.00
2 Customer2 12/7/22 12/7/22 5 3 2 Milk $1.00

Ultimately I am trying to feed this data into Carbone.io from Retool Workflow to make a PDF sales order using workflow, which I believe needs to be JSON similar to below

"SalesOrderID": 2,
"Customer": "Customer2",
"SoldDate": "12/7/22",
"LineItems": {ArrayOfLineItems}

I've tried selecting all Sales orders and then using a workflow loop to iterate over each one, selecting all the line items for each line in the sales order. This gives me the line items for each sales order, but I can't seem to figure out how to get the line items and sales order in the same JSON.

Would I be better to try to write a query that includes all the lines as a JSON array in a column?

Sorry for the long post, but appreciate any feedback or suggestions on the best way to attempt this!

CodePudding user response:

Something like this?

SELECT * FROM SalesOrder
JOIN Lines1 ON SalesOrder.SalesOrderID = Lines1.SalesOrderID and Lines1.LineItemId= 1
LEFT OUTER JOIN Lines2 ON SalesOrder.SalesOrderID = Lines2.SalesOrderID and Lines2.LineItemId= 2
LEFT OUTER JOIN Lines3 ON SalesOrder.SalesOrderID = Lines3.SalesOrderID and Lines3.LineItemId= 3

Here is the stuff function. Might get you closer to the format you're looking for.

select t.*
,(SELECT
        DISTINCT
            STUFF((select ','   l.Product
                    FROM LineTable l
                    WHERE l.SalesOrderId = t.SalesOrderId
                    FOR XML path('')),1,1,'') as 'Product'
    ) 
from SalesTable t

CodePudding user response:

You can get the JSON directly in Oracle using:

SELECT JSON_OBJECT(
         KEY 'salesOrderId' VALUE s.salesOrderId,
         KEY 'customer'     VALUE s.customer,
         KEY 'soldDate'     VALUE s.soldDate,
         KEY 'shipDate'     VALUE s.shipDate,
         KEY 'lineItems'    VALUE l.lineItems FORMAT JSON
         RETURNING CLOB
       ) AS salesorder
FROM   salesorder s
       CROSS JOIN LATERAL (
         SELECT JSON_ARRAYAGG(
                  JSON_OBJECT(
                    KEY 'lineItemId' VALUE l.lineItemid,
                    KEY 'lineNumber' VALUE l.lineNumber,
                    KEY 'product'    VALUE l.product,
                    KEY 'price'      VALUE l.price
                  )
                  ORDER BY l.lineNumber
                  RETURNING CLOB
                ) AS lineItems
         FROM   lines l
         WHERE  l.salesorderid = s.salesorderid
       ) l

Which, for the sample data:

CREATE TABLE SalesOrder (SalesOrderID, Customer, SoldDate, ShipDate) AS
SELECT 1,   'Customer1', DATE '2022-07-12', DATE '2022-07-12' FROM DUAL UNION ALL
SELECT 2,   'Customer1', DATE '2022-07-12', DATE '2022-07-12' FROM DUAL UNION ALL
SELECT 3,   'Customer2', DATE '2022-07-12', DATE '2022-07-12' FROM DUAL;

CREATE TABLE Lines (LineItemID, LineNumber, SalesOrderID, Product, Price) AS
SELECT 1,   1,  1,  'Eggs',  1.00 FROM DUAL UNION ALL
SELECT 2,   2,  1,  'Milk',  1.00 FROM DUAL UNION ALL
SELECT 3,   1,  2,  'Bread', 1.00 FROM DUAL UNION ALL
SELECT 4,   2,  2,  'Eggs',  1.00 FROM DUAL UNION ALL
SELECT 5,   3,  2,  'Milk',  1.00 FROM DUAL UNION ALL
SELECT 6,   1,  3,  'Eggs',  1.00 FROM DUAL;

Outputs:

SALESORDER
{"salesOrderId":1,"customer":"Customer1","soldDate":"2022-07-12T00:00:00","shipDate":"2022-07-12T00:00:00","lineItems":[{"lineItemId":1,"lineNumber":1,"product":"Eggs","price":1},{"lineItemId":2,"lineNumber":2,"product":"Milk","price":1}]}
{"salesOrderId":2,"customer":"Customer1","soldDate":"2022-07-12T00:00:00","shipDate":"2022-07-12T00:00:00","lineItems":[{"lineItemId":3,"lineNumber":1,"product":"Bread","price":1},{"lineItemId":4,"lineNumber":2,"product":"Eggs","price":1},{"lineItemId":5,"lineNumber":3,"product":"Milk","price":1}]}
{"salesOrderId":3,"customer":"Customer2","soldDate":"2022-07-12T00:00:00","shipDate":"2022-07-12T00:00:00","lineItems":[{"lineItemId":6,"lineNumber":1,"product":"Eggs","price":1}]}

fiddle

  • Related