简体   繁体   中英

MySQL subquery - using alias from SELECT in WHERE conditions (no CTE)

I'm trying to find out where/how to implement subquery in below trimmed down example.

The issue is that I need to add hours depending on time zones and then return those fields.
At the same time though, I need to filter by the same fields, and for it to be accurate, I need them to already be adjusted to the correct time zone.

Can you please give me an advice on how I can work this out?

SELECT
od.ID AS 'Id',
CASE WHEN tzp.ZoneId='Etc/GMT-1'
    THEN ADDDATE(od.declaredStartTime, INTERVAL 1 HOUR)
    ELSE od.declaredStartTime END AS 'Collection date\\time',
CASE WHEN tzd.ZoneId='Etc/GMT-1'
    THEN ADDDATE(od.declaredEndTime, INTERVAL 1 HOUR)
    ELSE od.declaredEndTime END AS 'Delivery date\\time'
FROM orders od
LEFT OUTER JOIN time_zone AS tzp
    ON (tzp.ID = od.pickupTimeZone_ID)
LEFT OUTER JOIN time_zone AS tzd
    ON (tzd.ID = od.dropTimeZone_ID)
WHERE
    od.IS_DELETED != '1'
    -- AND 'Delivery date\\time' >= '2019-06-30' --<< This won't work because
    -- AND 'Delivery date\\time' <= '2019-08-01' --<< SELECT is the last operation

I unfortunately have no option to use CTE, as our MySQL is 5.6 and CTE is apparently available from 8.0

Edited: to make the code sample valid

Edit: full working version of the command

SELECT
    od.ID                                               AS 'Id',
    od.referenceNumber                                  AS 'Reference number',
    od.secondReferenceNumber                            AS 'Second reference number',
    od.status                                           AS 'Status',
    ADDDATE(od.created, INTERVAL 1 HOUR)                AS 'Creation date/time', -- BST not accounted for!
    st.name                                             AS 'Shipment type',
    IFNULL(sp.name, '')                                 AS 'Supplier',
    ls.name                                             AS 'Collection location',
    CASE WHEN tzp.ZoneId='Etc/GMT-1'
        THEN ADDDATE(od.declaredStartTime, INTERVAL 1 HOUR)
        ELSE od.declaredStartTime END                   AS 'Collection date\\time',
    ld.name                                             AS 'Delivery location',
    CASE WHEN tzd.ZoneId='Etc/GMT-1'
        THEN ADDDATE(od.declaredEndTime, INTERVAL 1 HOUR)
        ELSE od.declaredEndTime END                     AS 'Delivery date\\time',
    od.supplierRate                                     AS 'Supplier rate (pounds)',
    IFNULL(od.alternativeSupplierRate, '')              AS 'Supplier alternative rate (pounds)',
    od.supplierTransportTotal                           AS 'Supplier total rate (pounds)',
    od.customerRate                                     AS 'Customer rate (pounds)',
    IFNULL(od.alternativeCustomerRate, '')              AS 'Customer alternative rate (pounds)',
    od.customerTransportTotal                           AS 'Customer total rate (pounds)',
    IFNULL(od.quantity, '')                             AS 'Quantity',
    IFNULL(od.weight, '')                               AS 'Weight',
    IFNULL(od.palletQuantity, '')                       AS 'Pallet quantity',
    IFNULL(od.kmsTravelled, '')                         AS 'Kms travelled',
    IFNULL(od.carbonFootprint, '')                      AS 'Carbon footprint',
    IFNULL(od.performanceScore, '')                     AS 'Performance score',
    od.fuel_surcharge                                   AS 'Fuel surcharge (pounds)',
    od.caf_surcharge                                    AS 'CAF surcharge (pounds)',
    IFNULL(od.supplierFuelSurcharge, '')                AS 'Supplier fuel surcharge (pounds)',
    IFNULL(od.supplierCAFSurcharge, '')                 AS 'Supplier CAF surcharge (pounds)',
    od.vehiclesRegistrationInformation                  AS 'Vehicles registration information',
    od.trailerIsChecked                                 AS 'Trailer is checked',
    od.checkedTrailerNumber                             AS 'Trailer number',
    od.additionalPickupsNumber                          AS 'Number of additional pickups',
    od.additionalDropsNumber                            AS 'Number of additional drops',
    IFNULL(od.customerRateFromPricingMatrix, '')        AS 'Customer rate from pricing matrix',
    IFNULL(od.supplierRateFromPricingMatrix, '')        AS 'Supplier rate from pricing matrix',
    IF(el.shipmentLateType IS NULL, 'FALSE', 'TRUE')    AS 'Is late', -- NULL or late type
    IFNULL(rc.name, '')                                 AS 'Late category',
    od.comment                                          AS 'Comments',
    od.customerComment                                  AS 'Customer comments',
    od.supplierComment                                  AS 'Supplier comments',
    IF(od.rejectedByCustomer, 'TRUE', 'FALSE')          AS 'Rejected by customer',  -- dbck
    IFNULL(uc.name, '')                                 AS 'Unallocation reason',
    IFNULL(us2.name, '')                                AS 'Unallocation user',
    IFNULL(ur.created, '')                              AS 'Unallocation date/time',
    IFNULL(sp2.name, '')                                AS 'Unallocation supplier',
    IFNULL(od.supplierRankPosition, '')                 AS 'Supplier\'s position',
    IFNULL(od.supplierRank, '')                         AS 'Supplier\'s rank',
    IFNULL(od.highestRankOnAllocation, '')              AS 'Highest rank',
    IF(od.proveOfDelivery IS NULL, 'FALSE', 'TRUE')     AS 'POD attached', -- NULL or filename
    IFNULL(od.supplierInvoiceNumber, '')                AS 'Supplier Sage invoice number',
    IFNULL(od.customerInvoiceNumber, '')                AS 'Customer Sage invoice number',
    IFNULL(od.purchaseOrderNumber, '')                  AS 'Purchase orders batch number',
    IFNULL(vc.name, '')                                 AS 'Vehicle',
    IFNULL(od.invoicingKmsTravelled, '0')               AS 'Actual Kms travelled',
    IFNULL(od.duration, '0')                            AS 'Actual duration',
    IFNULL(vc.location, '')                             AS 'Vehicle location',  -- loc verify
    IFNULL(tp.idling, '0')                              AS 'Idling time',
    IFNULL(tp.fuelUsed, '0')                            AS 'Fuel used',
    IF(od.hasDeliveryDiscrepancy, 'TRUE', 'FALSE')      AS 'Has delivery discrepancy',
    IFNULL(od.deliveryDiscrepancyReasonID, '')          AS 'Delivery discrepancy reason Id',
    IFNULL(dc1.title, '')                               AS 'Delivery discrepancy reason name',
    IFNULL(od.deliveryDiscrepancyComment, '')           AS 'Delivery discrepancy comment',
    IF(od.hasHazardousGoods, 'TRUE', 'FALSE')           AS 'Has hazardous goods',
    IFNULL(od.surchargeReasonId, '')                    AS 'Surcharge reason Id',
    IFNULL(dc2.title, '')                               AS 'Surcharge reason name',
    od.bookingReference                                 AS 'Booking reference',
    od.driverName                                       AS 'Driver',
    CASE
        WHEN ISNULL(wr.passed) THEN                     'Not started'
        WHEN SUM(CASE WHEN wr.passed=0 THEN 1 ELSE 0 END)=0
        THEN                                            'Passed'
        ELSE                                            'Failed'
    END                                                 AS 'Walkaround Check status',
    SUM(CASE
        WHEN wr.passed=0 THEN 1 ELSE 0
    END)                                                AS 'Walkaround Check failed count'
FROM orders od
LEFT OUTER JOIN shipment_type               AS st
    ON (st.ID = od.shipmentType_ID)
LEFT OUTER JOIN shipment_unallocate_reason  AS ur
    ON (ur.shipment_ID = od.ID)
LEFT OUTER JOIN unallocate_reason_codes     AS uc
    ON (uc.ID = ur.reasonCode_ID)
LEFT OUTER JOIN user                        AS us2
    ON (us2.ID = ur.user_ID)
LEFT OUTER JOIN suppliers                   AS sp
    ON (sp.ID = od.supplier_ID)
LEFT OUTER JOIN suppliers                   AS sp2
    ON (sp2.ID = ur.supplier_ID)
LEFT OUTER JOIN walk_around_check           AS wc
    ON (wc.shipment_id = od.ID)
LEFT OUTER JOIN walk_around_check_result    AS wr
    ON (wr.check_id = wc.ID)
LEFT OUTER JOIN walk_around_check_item      AS wi
    ON (wr.check_item_id = wi.id)
LEFT OUTER JOIN landmark                    AS ld
    ON (ld.ID = od.destination_id)
LEFT OUTER JOIN landmark                    AS ls
    ON (ls.ID = od.source_id)
LEFT OUTER JOIN landmark                    AS lw
    ON (lw.ID = wc.location_id)
LEFT OUTER JOIN time_zone                   AS tzp
    ON (tzp.ID = od.pickupTimeZone_ID)
LEFT OUTER JOIN time_zone                   AS tzd
    ON (tzd.ID = od.dropTimeZone_ID)
LEFT OUTER JOIN user                        AS us
    ON (us.ID = wc.driver_id)
LEFT OUTER JOIN shipment_event              AS el
    ON (el.Shipment_ID = od.ID) -- AND se.shipmentLateType = 'DELIVERY_LATE'
LEFT OUTER JOIN late_reason_codes           AS rc
    ON (rc.ID = el.reasonCode_ID)
LEFT OUTER JOIN dictionary                  AS dc1
    ON (dc1.id = od.deliveryDiscrepancyReasonID)
LEFT OUTER JOIN dictionary                  AS dc2
    ON (dc2.id = od.surchargeReasonId)
LEFT OUTER JOIN trips                       AS tp
    ON (tp.shipment_ID = od.ID)
LEFT OUTER JOIN vehicle                     AS vc
    ON (vc.id = tp.vehicle_ID)
WHERE od.IS_DELETED != '1'
    -- NOTE: Have to compare dates incl. timezone changes!!!
    -- AND 'Collection date\\time' >= '2019-06-30'
    -- AND 'Collection date\\time' <= '2019-08-01'
    -- AND 'Delivery date\\time' >= '2019-06-30'
    -- AND 'Delivery date\\time' <= '2019-08-01'
GROUP BY od.ID  -- required in conjunction with SUM to not return single row
ORDER BY od.ID ASC

You must repeat the CASE statement in the WHERE clause:

AND CASE 
  WHEN tzd.ZoneId='Etc/GMT-1'THEN ADDDATE(od.declaredEndTime, INTERVAL 1 HOUR)
  ELSE od.declaredEndTime 
END BETWEEN '2019-06-30' AND '2019-08-01'

instead of:

AND 'Delivery date\\time' >= '2019-06-30'
AND 'Delivery date\\time' <= '2019-08-01'


Another way of doing this is using a HAVING clause instead of WHERE but this would need to nest your query as a subquery because you already use GROUP BY :

SELECT Id, `Collection date\\time`, `Delivery date\\time` 
FROM (
  SELECT
  od.ID AS 'Id',
  CASE WHEN tzp.ZoneId='Etc/GMT-1'
    THEN ADDDATE(od.declaredStartTime, INTERVAL 1 HOUR)
    ELSE od.declaredStartTime END AS `Collection date\\time`,
  CASE WHEN tzd.ZoneId='Etc/GMT-1'
    THEN ADDDATE(od.declaredEndTime, INTERVAL 1 HOUR)
    ELSE od.declaredEndTime END AS `Delivery date\\time`,
  FROM orders od
  LEFT OUTER JOIN time_zone AS tzp
    ON (tzp.ID = od.pickupTimeZone_ID)
  LEFT OUTER JOIN time_zone AS tzd
    ON (tzd.ID = od.dropTimeZone_ID)
  HAVING
    od.IS_DELETED != '1'
    AND `Delivery date\\time` >= '2019-06-30' --<< This won't work because
    AND `Delivery date\\time` <= '2019-08-01' --<< SELECT is the last operation
)
GROUP....

Note: since you use the GROUP BY clause what is the point of these calculated columns in the select list? Your statement should not even run. Or maybe it's not the exact code you really have.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM