Хорошо, я закончил тем, что выбрал позиции из SOITEM, присоединил их к первому запросу для деталей позиции, а затем ко второму запросу для итоговых данных по заказу на продажу.
Это некрасиво, это повторяется, и должен быть лучший способ (да, CTE, но MySQL 5.7 не позволяет этого), но он работает. Если у кого-то есть предложение, совместимое с версией 5.7, чтобы сделать это менее повторяющимся, я был бы рад его увидеть. : 0)
SELECT
/* ORIG: $P!{cbGroupBy} AS GROUPBY*/
LOCATIONGROUP.NAME AS GROUPBY
, LOCATIONGROUP.NAME AS LG
, CUSTOMER.NAME AS CUSTOMER
, SO.NUM AS SO
, SO.DATEISSUED
, SOSTATUS.NAME AS STATUS /* SO status */
, SO.SALESMAN AS "user"
/* wPARAMETER: , (case when $P{ckShowHistoricalProductNumber} = 1 then soitem.productnum else product.num end) AS PRODUCTNUM*/
, (case when 1 = 1 then soitem.productnum else product.num end) AS PRODUCTNUM
, UOM.CODE AS SOITEMUOMCODE
, SOITEM.DESCRIPTION
, SOITEM.ID AS ITEMID
, soitem.SOID
, soitem.SOLINEITEM
, solineitems.SOITEMSTATUS
, soitem.UNITPRICE
, soitem.ADJUSTAMOUNT
, soitem.QTYTOFULFILL
, IFNULL(solineitems.LIAMTORDEREDTOTAL, 0) as LIAMTORDEREDTOTAL /* OPRICE equivalent */
, IFNULL(solineitems.LIQTYSHIPPEDPRIOR , 0) as LIQTYSHIPPEDPRIOR
, IFNULL(solineitems.LIAMTSHIPPEDPRIOR , 0) as LIAMTSHIPPEDPRIOR
, IFNULL(solineitems.LIQTYSHIPPEDTODAY , 0) as LIQTYSHIPPEDTODAY
, IFNULL(solineitems.LIAMTSHIPPEDTODAY , 0) as LIAMTSHIPPEDTODAY /* FPRICE replacement; limited to date of report ONLY */
, IFNULL(solineitems.LIQTYSHIPPEDTODATE , 0) as LIQTYSHIPPEDTODATE
, IFNULL(solineitems.LIAMTSHIPPEDTODATE , 0) as LIAMTSHIPPEDTODATE
, IFNULL(solineitems.LIQTYREMAINING , 0) as LIQTYREMAINING
, IFNULL(solineitems.LIAMTREMAINING , 0) as LIAMTREMAINING /* OPRICE - FPRICE replacement */
, IFNULL(sototals.SOAMTORDERTOTAL, 0) as SOAMTORDERTOTAL /* SORDER.ORDERED equivalent */
, IFNULL(sototals.SOAMTSHIPPEDPRIOR, 0) as SOAMTSHIPPEDPRIOR
, IFNULL(sototals.SOAMTSHIPPEDTODAY, 0) as SOAMTSHIPPEDTODAY /* SORDER.SHIPPED replacement; limited to date of report ONLY */
, IFNULL(sototals.SOAMTSHIPPEDTODATE, 0) as SOAMTSHIPPEDTODATE
, IFNULL(sototals.SOAMTREMAINING, 0) as SOAMTREMAINING /* SORDER.ORDERED - SORDER.SHIPPED replacement */
, MIN(SOITEM.DATESCHEDULEDFULFILLMENT) AS DATESCHEDULEDFULFILLMENT
, SOITEM.DATESCHEDULEDFULFILLMENT AS ITEMFULFILLMENT
, MIN(SO.DATEISSUED) AS MINDATEISSUED
, POSTSO.POSTDATE
, CURRENCY.SYMBOL
, SO.CUSTOMERPO
, STATECONST.CODE AS SHIPTOSTATE
, SOITEM.DATELASTFULFILLMENT
, SO.DATEFIRSTSHIP
, SO.DATECOMPLETED
FROM SOITEM
LEFT OUTER JOIN SO ON soitem.SOID = so.ID
LEFT JOIN STATECONST ON so.SHIPTOSTATEID = stateconst.ID
INNER JOIN LOCATIONGROUP ON locationgroup.ID = so.LOCATIONGROUPID
INNER JOIN CUSTOMER ON customer.ID = so.CUSTOMERID
INNER JOIN SOSTATUS ON sostatus.ID = so.STATUSID
LEFT JOIN PRODUCT ON soitem.PRODUCTID = product.ID
JOIN QBCLASS ON qbclass.ID = so.QBCLASSID
LEFT JOIN CURRENCY ON currency.HOMECURRENCY = 1
LEFT JOIN (
SELECT
postso.SOID AS SOID,
MAX(postso.POSTDATE) AS POSTDATE
FROM POSTSO
/* withPARAMETER: WHERE postso.POSTDATE BETWEEN $P{dateRange1} AND DATE_SUB($P{dateRange2}, INTERVAL 1 SECOND)*/
WHERE postso.POSTDATE BETWEEN '2020-05-27' AND DATE_SUB('2020-05-27', INTERVAL 1 SECOND)
GROUP BY postso.SOID
) AS postso ON so.ID = postso.SOID
INNER JOIN UOM ON uom.ID = soitem.UOMID
/* SO TOTALS */
LEFT OUTER JOIN (
SELECT
soitem.SOID
, SUM(soitem.UNITPRICE * soitem.QTYTOFULFILL + soitem.ADJUSTAMOUNT) AS SOAMTORDERTOTAL
, SUM(ROUND(
((IFNULL(qsp.QTYFULFILLEDPRIOR, 0) * soitem.UNITPRICE) +
((IF(soitem.QTYTOFULFILL = 0,0,soitem.ADJUSTAMOUNT / soitem.QTYTOFULFILL) * IFNULL(qsp.QTYFULFILLEDPRIOR, 0)))) * 10
,1) / 10) AS SOAMTSHIPPEDPRIOR
, SUM(ROUND(
(((IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) - IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) * soitem.UNITPRICE) +
(IF(soitem.QTYTOFULFILL = 0,0,soitem.ADJUSTAMOUNT / soitem.QTYTOFULFILL) * (IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) - IFNULL(qsp.QTYFULFILLEDPRIOR, 0)))) * 10
,1) / 10) AS SOAMTSHIPPEDTODAY
, SUM(ROUND(
((IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) * soitem.UNITPRICE) +
(IF(soitem.QTYTOFULFILL = 0,0,soitem.ADJUSTAMOUNT / soitem.QTYTOFULFILL) * IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0)))) * 10
,1) / 10) AS SOAMTSHIPPEDTODATE
, SUM(ROUND(
(((soitem.QTYTOFULFILL - IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0))) * soitem.UNITPRICE) +
(IF(soitem.QTYTOFULFILL = 0,0,soitem.ADJUSTAMOUNT / soitem.QTYTOFULFILL) * (soitem.QTYTOFULFILL - IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0))))) * 10
,1) / 10) AS SOAMTREMAINING
FROM SOITEM
/* get quantity shipped PRIOR to this date */
LEFT OUTER JOIN
(
SELECT
SOID
, SOLINEITEM
, IFNULL(MAX(soitem_aud.QTYFULFILLED),0) as QTYFULFILLEDPRIOR
FROM SOITEM_AUD
/* withPARAMETER: WHERE DATE_FORMAT(soitem_aud.DATELASTFULFILLMENT, '%Y %m %d') < DATE_FORMAT($P{dateRange1}, '%Y %m %d') */
WHERE DATE_FORMAT(soitem_aud.DATELASTFULFILLMENT, '%Y %m %d') < DATE_FORMAT('2020-05-27', '%Y %m %d')
AND soitem_aud.PRODUCTNUM NOT IN ('Shipping', 'Shipping Out')
GROUP BY
SOID
, SOLINEITEM
) AS qsp ON soitem.SOID = qsp.SOID AND soitem.SOLINEITEM = qsp.SOLINEITEM
/* get quantity shipped ON this date */
LEFT OUTER JOIN
(
SELECT
soitem.SOID
, soitem.SOLINEITEM
, IFNULL(soitem_aud.QTYFULFILLED, 0) as QTYFULFILLEDTODATE /* INCLUDES items fulfilled THIS DATE */
FROM SOITEM
LEFT OUTER JOIN SOITEM_AUD ON soitem.SOID = soitem_aud.SOID AND soitem.SOLINEITEM = soitem_aud.SOLINEITEM
/* withPARAMETER: WHERE DATE_FORMAT(soitem_aud.DATELASTFULFILLMENT, '%Y %m %d') = DATE_FORMAT($P{dateRange1}, '%Y %m %d') */
WHERE DATE_FORMAT(soitem_aud.DATELASTFULFILLMENT, '%Y %m %d') = DATE_FORMAT('2020-05-27', '%Y %m %d')
AND soitem_aud.PRODUCTNUM NOT IN ('Shipping', 'Shipping Out')
GROUP BY
SOID
, SOLINEITEM
) AS qftd ON soitem.SOID = qftd.SOID AND soitem.SOLINEITEM = qftd.SOLINEITEM
WHERE soitem.PRODUCTNUM NOT IN ('Shipping', 'Shipping Out')
GROUP BY
soitem.SOID
) as SOTOTALS ON soitem.SOID = sototals.SOID
/* LINE ITEM DETAILS */
LEFT OUTER JOIN (
SELECT
soitem.SOID
, soitem.SOLINEITEM
, IFNULL(qftd.SOITEMSTATUSNAME, IFNULL(qsp.SOITEMSTATUSNAME, 'Unknown')) AS SOITEMSTATUS
, soitem.QTYTOFULFILL * soitem.UNITPRICE + soitem.ADJUSTAMOUNT as LIAMTORDEREDTOTAL
, IFNULL(qsp.QTYFULFILLEDPRIOR, 0) as LIQTYSHIPPEDPRIOR
, ROUND(
((IFNULL(qsp.QTYFULFILLEDPRIOR, 0) * soitem.UNITPRICE) +
((IF(soitem.QTYTOFULFILL = 0,0,soitem.ADJUSTAMOUNT / soitem.QTYTOFULFILL) * IFNULL(qsp.QTYFULFILLEDPRIOR, 0)))) * 10
,1) / 10 AS LIAMTSHIPPEDPRIOR
, IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) - IFNULL(qsp.QTYFULFILLEDPRIOR, 0) as LIQTYSHIPPEDTODAY
, ROUND(
(((IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) - IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) * soitem.UNITPRICE) +
(IF(soitem.QTYTOFULFILL = 0,0,soitem.ADJUSTAMOUNT / soitem.QTYTOFULFILL) * (IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) - IFNULL(qsp.QTYFULFILLEDPRIOR, 0)))) * 10
,1) / 10 AS LIAMTSHIPPEDTODAY
, IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) as LIQTYSHIPPEDTODATE
, ROUND(
((IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) * soitem.UNITPRICE) +
(IF(soitem.QTYTOFULFILL = 0,0,soitem.ADJUSTAMOUNT / soitem.QTYTOFULFILL) * IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, IFNULL(qsp.QTYFULFILLEDPRIOR, 0))))) * 10
,1) / 10 AS LIAMTSHIPPEDTODATE
, soitem.QTYTOFULFILL - IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0)) as LIQTYREMAINING
, ROUND(
(((soitem.QTYTOFULFILL - IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0))) * soitem.UNITPRICE) +
(IF(soitem.QTYTOFULFILL = 0,0,soitem.ADJUSTAMOUNT / soitem.QTYTOFULFILL) * (soitem.QTYTOFULFILL - IFNULL(qftd.QTYFULFILLEDTODATE, IFNULL(qsp.QTYFULFILLEDPRIOR, 0))))) * 10
,1) / 10 AS LIAMTREMAINING
FROM SOITEM
/* get quantity shipped PRIOR to this date */
LEFT OUTER JOIN
(
SELECT
SOID
, SOLINEITEM
, soitemstatus.NAME as SOITEMSTATUSNAME
, IFNULL(MAX(soitem_aud.QTYFULFILLED),0) as QTYFULFILLEDPRIOR
FROM SOITEM_AUD
INNER JOIN SOITEMSTATUS ON soitem_aud.STATUSID = soitemstatus.ID
/* withPARAMETER: WHERE DATE_FORMAT(soitem_aud.DATELASTFULFILLMENT, '%Y %m %d') < DATE_FORMAT($P{dateRange1}, '%Y %m %d') */
WHERE DATE_FORMAT(soitem_aud.DATELASTFULFILLMENT, '%Y %m %d') < DATE_FORMAT('2020-05-27', '%Y %m %d')
AND soitem_aud.PRODUCTNUM NOT IN ('Shipping', 'Shipping Out')
GROUP BY
SOID
, SOLINEITEM
ORDER BY SOID, SOLINEITEM, soitem_aud.DATELASTFULFILLMENT DESC
) AS qsp ON soitem.SOID = qsp.SOID AND soitem.SOLINEITEM = qsp.SOLINEITEM
/* get quantity shipped ON this date */
LEFT OUTER JOIN
(
SELECT
soitem.SOID
, soitem.SOLINEITEM
, soitemstatus.NAME as SOITEMSTATUSNAME
, IFNULL(soitem_aud.QTYFULFILLED, 0) as QTYFULFILLEDTODATE /* INCLUDES items fulfilled THIS DATE */
FROM SOITEM
LEFT OUTER JOIN SOITEM_AUD ON soitem.SOID = soitem_aud.SOID AND soitem.SOLINEITEM = soitem_aud.SOLINEITEM
INNER JOIN SOITEMSTATUS ON soitem_aud.STATUSID = soitemstatus.ID
/* withPARAMETER: WHERE DATE_FORMAT(soitem_aud.DATELASTFULFILLMENT, '%Y %m %d') = DATE_FORMAT($P{dateRange1}, '%Y %m %d') */
WHERE DATE_FORMAT(soitem_aud.DATELASTFULFILLMENT, '%Y %m %d') = DATE_FORMAT('2020-05-27', '%Y %m %d')
AND soitem_aud.PRODUCTNUM NOT IN ('Shipping', 'Shipping Out')
GROUP BY
SOID
, SOLINEITEM
) AS qftd ON soitem.SOID = qftd.SOID AND soitem.SOLINEITEM = qftd.SOLINEITEM
WHERE soitem.PRODUCTNUM NOT IN ('Shipping', 'Shipping Out')
GROUP BY
soitem.SOID
, soitem.SOLINEITEM
) as SOLINEITEMS ON soitem.SOID = solineitems.SOID AND soitem.SOLINEITEM = solineitems.SOLINEITEM
WHERE soitem.PRODUCTNUM NOT IN ('Shipping', 'Shipping Out')
/* withPARAMETER: AND
soitem.TYPEID IN (10,11,12,$P!{ckIncludeReturns},21,30,31,50,60,80)
AND so.LOCATIONGROUPID IN ($P!{locationGroupID})
AND so.CUSTOMERID LIKE $P{customerID}
AND soitem.QBCLASSID LIKE $P{qbClassID}
AND UPPER(so.SALESMAN) LIKE UPPER($P{salesPerson})
AND so.STATUSID IN ($P{ckEstimate}, $P{ckIssued}, $P{ckInProgress}, $P{ckFulfilled}, $P{ckClosedShort}, $P{ckVoided}, $P{ckExpired})
AND COALESCE(product.NUM,'') LIKE $P{productNum}
AND COALESCE(stateconst.NAME,'') LIKE $P!{cbShipToState/Province}
*/
AND soitem.SOID = 8369 /* TESTING PURPOSES ONLY */
GROUP BY soitem.SOID, soitem.SOLINEITEM
ORDER BY soitem.SOID, soitem.SOLINEITEM