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

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.

Related

Convert mysql query to sqlite

I am new to sqlite3.I am currently using mysql. But I will be migrating it to sqlite3.
I am calculating month end balance
SELECT c.country,
Date_format(Last_day(Str_to_date(dt.date, '%m/%d/%Y')), '%Y/%m/%d')
AS Month_End_Balance,
Sum(dt.amount) AS in_Euro
FROM deposit_transactions AS dt
LEFT JOIN customers AS c
ON c.customer_id = dt.customer_id
GROUP BY c.country,
Month_End_Balance
order by Month_End_Balance desc
Need help in converting it to sqlite
Question
Need help in Last_Day function alternative in sqlite
Refer below query for SQLITE -
Please make adjustment as per needed date format.
with new_dep_trx as (
select deposit_id,customer_id,
transaction_type,amount,currency,
case when (length(dt.date)=8 or length(dt.date)=9) and instr(substr(dt.date,1,2),'/')>0
then
date(substr(dt.date,length(dt.date)-3,4)||'-0'||substr(dt.date,1,1)||'-0'||substr(dt.date,3,1))
when length(dt.date)=9 and instr(substr(dt.date,1,2),'/')=0
then
date(substr(dt.date,length(dt.date)-3,4)||'-'||substr(dt.date,1,2)||'-0'||substr(dt.date,4,1))
else
date(substr(dt.date,length(dt.date)-3,4)||'-'||substr(dt.date,1,2)||'-'||substr(dt.date,4,2)) end date_col
from deposit_transactions dt
)
select
c.country,
strftime('%Y-%m',dt.date_col) as month,
strftime('%m/%d/%Y',date(dt.date_col,'start of month','+1 month','-1 day')) as last_day_of_month,
strftime('%Y/%m/%d',date(dt.date_col,'start of month','+1 month','-1 day')) as last_day_of_month_your_format,
SUM(
dt.amount *
(CASE WHEN dt.currency = 'GBP' THEN .85 ELSE 1 END) *
(CASE WHEN dt.transaction_type = 'pay_in' THEN 1 ELSE -1 END)
) amount_eur
FROM new_dep_trx dt
LEFT JOIN customers c ON c.customer_id = dt.customer_id
GROUP BY c.country, last_day_of_month_your_format;
Modified DB fiddle.
First, you must update the column date of the table deposit_transactions so that it has the format YYYY-mm-dd the only text date format that you can use with SQLite's datetime functions:
UPDATE deposit_transactions
SET date = SUBSTR(date, -4) || '-' ||
printf('%02d', date + 0) || '-' ||
printf('%02d', SUBSTR(date, INSTR(date, '/') + 1, 2) + 0);
Now, you can use the function date() to get the last day of each month with:
date(date, 'start of month', '+1 month', '-1 day')
So, your query should be:
SELECT c.country,
date(dt.date, 'start of month', '+1 month', '-1 day') AS Month_End_Balance,
SUM(dt.amount *
CASE WHEN dt.currency = 'GBP' THEN .85 ELSE 1 END *
CASE WHEN dt.transaction_type = 'pay_in' THEN 1 ELSE -1 END
) AS amount_eur
FROM deposit_transactions AS dt LEFT JOIN customers AS c
ON c.customer_id = dt.customer_id
GROUP BY c.country, Month_End_Balance
ORDER BY Month_End_Balance DESC;
If you want to format the dates of the resultset to mm/dd/YYYY and sort properly by the date and not the formatted date which would sort incorrectly:
SELECT c.country,
strftime('%m/%d/%Y', date(dt.date, 'start of month', '+1 month', '-1 day')) AS Month_End_Balance,
SUM(dt.amount *
CASE WHEN dt.currency = 'GBP' THEN .85 ELSE 1 END *
CASE WHEN dt.transaction_type = 'pay_in' THEN 1 ELSE -1 END
) AS amount_eur
FROM deposit_transactions AS dt LEFT JOIN customers AS c
ON c.customer_id = dt.customer_id
GROUP BY c.country, date(dt.date, 'start of month', '+1 month', '-1 day')
ORDER BY date(dt.date, 'start of month', '+1 month', '-1 day') DESC;
See the demo.

How to list order items with order total per item

I have two tables: booking and order_items where booking has many order_items. I need to create a query where I list all order_items group by booking id but in each item line I need to show the total of the booking (for instance, booking id 1 has 2 order_items costing £10 each so I need the query to show:)
item 1 name price (£10) discount booking total (in this case £20)
I have the following query:
SELECT
b.partner_order_id,
'Store Name' as 'Store',
CONCAT_WS(' ', b.customer_firstname, b.customer_lastname) AS 'Name',
'1' as 'Quantity',
oi.order_price as 'Price',
oi.discount as 'Discount',
SUM(order_price - discount) as 'Payment',
'0' as 'Shipping',
'Sale' as 'Transaction',
oi.order_sku as 'SKU',
oi.order_name as 'Description',
oi.order_color as 'Colour',
oi.order_size as 'Size'
FROM booking AS b
JOIN order_items oi on b.booking_id = oi.booking_id
WHERE
b.delivery_date >= DATE(NOW()) - INTERVAL 8 DAY and
b.partner_id = 36 and
oi.item_accepted = 1
GROUP BY oi.id
Which does almost everything I need apart from giving me the total per booking on each item line. Any ideas?
you need to add a sub query to your select like this:
SELECT
b.partner_order_id,
'Store Name' as 'Store',
CONCAT_WS(' ', b.customer_firstname, b.customer_lastname) AS 'Name',
'1' as 'Quantity',
oi.order_price as 'Price',
oi.discount as 'Discount',
SUM(order_price - discount) as 'Payment',
'0' as 'Shipping',
'Sale' as 'Transaction',
oi.order_sku as 'SKU',
oi.order_name as 'Description',
oi.order_color as 'Colour',
oi.order_size as 'Size',
(SELECT SUM(order_price) FROM order_items WHERE booking_id = b.booking_id) AS total
FROM booking AS b
JOIN order_items oi on b.booking_id = oi.booking_id
WHERE
b.delivery_date >= DATE(NOW()) - INTERVAL 8 DAY and
b.partner_id = 36 and
oi.item_accepted = 1
GROUP BY oi.id

Speed up query on mysql view

I have a very long query with multiple sub queries and this query can take up to 30 sec to complete.
Is there a better way to construct the query?
select FROM_UNIXTIME(peg_remedy_incident.PEG_OutageStartTime,"%m-%d-%Y") AS 'Incident Date', PEG_Category AS Category, (select GROUP_CONCAT(DISTINCT peg_frm_inc_incidentXnetworkRe.Market ORDER BY Market) from peg_frm_inc_incidentXnetworkRe WHERE peg_frm_inc_incidentXnetworkRe.IncidentVisibleID=peg_frm_inc_incidentXcustomerR.IncidentID AND peg_frm_inc_incidentXcustomerR.CustomerCode=peg_frm_inc_incidentXnetworkRe.CustomerCode AND peg_frm_inc_incidentXnetworkRe.RadioButton_Types IN (1,2) GROUP BY peg_frm_inc_incidentXnetworkRe.IncidentVisibleID, peg_frm_inc_incidentXnetworkRe.CustomerCode) AS Market,peg_frm_inc_incidentXcustomerR.CustomerName AS 'Customer' , peg_frm_inc_incidentXcustomerR.CustomerTicket AS 'Customer TT#', peg_remedy_incident.PEG_NetworkProvider AS 'Network Provider', peg_remedy_incident.PEG_ProviderTicketNumber AS 'Network Provider TT#',
peg_remedy_incident.PEG_ThirdPartyVendor AS '3rd Party Support Vendor', peg_remedy_incident.PEG_ThirdPartyVendor_TT_ AS '3rd Party TT#','' AS 'Maintenance Window Outage? (Y/N)', TRIM(LEADING '0' FROM peg_frm_inc_incidentXcustomerR.IncidentID) AS 'TT#',FROM_UNIXTIME(peg_remedy_incident.PEG_OutageStartTime,"%m-%d-%Y %r") AS `Event Start Time`, FROM_UNIXTIME(peg_remedy_incident.PEG_OutageStopTime,"%m-%d-%Y %r") AS `Event Stop Time`,
'=(M{ROWID}-L{ROWID})*1440' AS 'Total Minutes', '=(M{ROWID}-L{ROWID})' AS 'Total Hours/Minutes','=(M{ROWID}-L{ROWID})*R{ROWID}*1440' AS ' Total Outage Minutes','=(M{ROWID}-L{ROWID})*R{ROWID}' AS ' Total Outage Hours/Minutes',
(select count(DISTINCT(Site_ID)) from peg_frm_inc_incidentXnetworkRe WHERE peg_frm_inc_incidentXnetworkRe.IncidentVisibleID=peg_frm_inc_incidentXcustomerR.IncidentID AND peg_frm_inc_incidentXcustomerR.CustomerCode=peg_frm_inc_incidentXnetworkRe.CustomerCode AND peg_frm_inc_incidentXnetworkRe.RadioButton_Types=1) AS 'Outage Sites Impacted',
(select count(DISTINCT(Circuit_ID)) from peg_frm_inc_incidentXnetworkRe WHERE peg_frm_inc_incidentXnetworkRe.IncidentVisibleID=peg_frm_inc_incidentXcustomerR.IncidentID AND
peg_frm_inc_incidentXcustomerR.CustomerCode=peg_frm_inc_incidentXnetworkRe.CustomerCode AND peg_frm_inc_incidentXnetworkRe.RadioButton_Types=1) AS 'Outage Circuits Impacted',
(select count(DISTINCT(Site_ID)) from peg_frm_inc_incidentXnetworkRe WHERE peg_frm_inc_incidentXnetworkRe.IncidentVisibleID=peg_frm_inc_incidentXcustomerR.IncidentID AND peg_frm_inc_incidentXcustomerR.CustomerCode=peg_frm_inc_incidentXnetworkRe.CustomerCode AND peg_frm_inc_incidentXnetworkRe.RadioButton_Types=2) AS 'Simplex Sites Impacted',
(select count(DISTINCT(Circuit_ID)) from peg_frm_inc_incidentXnetworkRe WHERE peg_frm_inc_incidentXnetworkRe.IncidentVisibleID=peg_frm_inc_incidentXcustomerR.IncidentID AND
peg_frm_inc_incidentXcustomerR.CustomerCode=peg_frm_inc_incidentXnetworkRe.CustomerCode AND peg_frm_inc_incidentXnetworkRe.RadioButton_Types=2) AS 'Simplex Circuits Impacted',
peg_remedy_incident.PEG_TechName AS 'Technician Dispatch', '' AS 'Summary & Ticket Notes', peg_remedy_incident.PEG_NetworkAvailabilityAffecti ,
CAST( CASE
WHEN peg_remedy_incident.PEG_Ring_Lateral = 'Lateral'
THEN 'Yes'
WHEN peg_remedy_incident.PEG_Ring_Lateral = 'Ring'
THEN 'No'
ELSE ''
END AS char(3)) as 'Lateral (Y/N)' ,
'' AS 'Backhaul/Non-Backhaul?', PEG_Resolution_Details AS 'Resolution Details',
PEG_CauseCode1 AS 'Cause Code 1', PEG_CauseCode2 AS 'Cause Code 2',
PEG_CauseCode3 AS 'Cause Code 3', PEG_CauseCode4 AS 'Cause Code 4', Root_Cause_Analysis AS 'Root Cause Analysis','' AS 'Notes',
(select GROUP_CONCAT(DISTINCT peg_frm_inc_incidentXwork_log.Notes ORDER BY Request_ID) AS 'Work Log1' from peg_frm_inc_incidentXwork_log WHERE peg_frm_inc_incidentXwork_log.Incident_ID=peg_frm_inc_incidentXcustomerR.IncidentID GROUP BY peg_frm_inc_incidentXwork_log.Incident_ID) as 'Work Log',
(select GROUP_CONCAT(DISTINCT peg_frm_inc_incidentXnetworkRe.Site_ID ORDER BY Site_ID) AS 'OutageSite List1' from peg_frm_inc_incidentXnetworkRe WHERE peg_frm_inc_incidentXnetworkRe.IncidentVisibleID=peg_frm_inc_incidentXcustomerR.IncidentID AND peg_frm_inc_incidentXcustomerR.CustomerCode=peg_frm_inc_incidentXnetworkRe.CustomerCode AND peg_frm_inc_incidentXnetworkRe.RadioButton_Types=1 GROUP BY peg_frm_inc_incidentXnetworkRe.IncidentVisibleID, peg_frm_inc_incidentXnetworkRe.CustomerCode) as 'Outage Site List'
FROM peg_frm_inc_incidentXcustomerR LEFT JOIN peg_frm_inc_incidentXnetworkRe ON peg_frm_inc_incidentXcustomerR.IncidentID=peg_frm_inc_incidentXnetworkRe.IncidentVisibleID
LEFT JOIN peg_remedy_incident ON peg_frm_inc_incidentXcustomerR.IncidentID=peg_remedy_incident.PEG_VisibleTicketID WHERE peg_frm_inc_incidentXnetworkRe.RadioButton_Types IN(1 ,2) AND peg_remedy_incident.PEG_VisibleTicketID>=000000000034000 GROUP BY peg_frm_inc_incidentXnetworkRe.IncidentVisibleID,peg_frm_inc_incidentXcustomerR.CustomerCode

SQL - Too many calls to subquery

The below query is fairly slow, in terms of the subquery selection for the "skill name". When I run a profile against the SQL execution I am getting far too many queries per line from the ACDCallinformation table against the sub query for skillname.
What is the best way of optimising this SQL query or is there a MySQL tool to help with checking on costs for a SQL query and optimising the script?
SELECT
CASE
WHEN(
SELECT
COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`)
FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL AND DATEofcall = DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
) IS NULL
THEN
0
ELSE
(
SELECT COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`)
FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL AND DATEofcall= DATE(NOW()) AND ag.skillid = acdcallinformation.skillid)
END AS 'Lost Calls',
CASE WHEN COUNT(acdcallinformation.idleonqueue) IS NULL THEN 0 ELSE COUNT(acdcallinformation.idleonqueue) END AS 'Total Calls',
CASE WHEN COUNT(acdcallinformation.`ANSWERTIME`) IS NULL THEN 0 ELSE COUNT(acdcallinformation.`ANSWERTIME`) END AS 'Answered',
(
SELECT
skillinfo.skillname
FROM skillinfo
WHERE skillinfo.pkey = acdcallinformation.skillid
) AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM `acdcallinformation` acdcallinformation
WHERE DATEOFCALL = DATE(NOW())
GROUP BY skill;
Not sure the best way show data:
ACDCALLINFORMATION - number of rows currently 3028
INSTIME PKEY DATEOFCALL CONNECTTIME FIRSTRING SKILLID
2012-07-19 14:50:16 19985 2012-07-19 14:50:16 14:50:16 5
SKILLINFO - Average number of rows is 5-10
INSTIME PKEY SKILLNAME
2012-07-01 13:12:01 1 Calls Outgoing
2012-07-01 13:12:01 2 Call Centre
2012-07-01 13:12:01 3 Accounts
2012-07-01 13:12:01 4 Reception
This is the output expected:
"Lost Calls" "Total Calls" "Answered" "Skill" "Average Answer Time" "Average Talk Time"
"1" "2" "1" "Accounts" "00:00:04" "00:00:01"
"0" "5" "5" "Service" "00:00:07" "00:01:20"
Try this, is using inner joins to improve performance and avoid unnecessary subquerys
SELECT
COALESCE(ag.skillcount, 0) AS 'Lost Calls',
CASE WHEN COUNT(acdcallinformation.idleonqueue) IS NULL THEN 0 ELSE COUNT(acdcallinformation.idleonqueue) END AS 'Total Calls',
CASE WHEN COUNT(acdcallinformation.`ANSWERTIME`) IS NULL THEN 0 ELSE COUNT(acdcallinformation.`ANSWERTIME`) END AS 'Answered',
si.skillname AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM `acdcallinformation` acdcallinformation
LEFT JOIN (
SELECT skillid, COUNT(`PKEY`) - COUNT(`ANSWERTIME`) skillcount
FROM acdcallinformation
WHERE (`COMPLETED`) = 1 AND answertime IS NULL AND DATEofcall = DATE(NOW())
) ag ON AND ag.skillid = acdcallinformation.skillid
LEFT JOIN skillinfo si ON si.pkey = acdcallinformation.skillid
WHERE DATEOFCALL = DATE(NOW())
GROUP BY si.skillname;
It looks like you're trying to ensure that NULLs are converted to 0s. Thus:
SELECT
IFNULL(
(SELECT COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`) FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL
AND DATEofcall = DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
), 0) AS 'Lost Calls',
IFNULL(COUNT(acdcallinformation.idleonqueue), 0) AS 'Total Calls',
IFNULL(COUNT(acdcallinformation.`ANSWERTIME`),0) AS 'Answered',
(
SELECT
skillinfo.skillname
FROM skillinfo
WHERE skillinfo.pkey = acdcallinformation.skillid
) AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM `acdcallinformation` acdcallinformation
WHERE DATEOFCALL = DATE(NOW())
GROUP BY skill;
Although, it might be easier to just convert those NULLs to zeros using the language that consumes this data... just a thought.
Also, my reading of the docs for COUNT make me think that it will never return NULL, thus:
SELECT
(SELECT COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`) FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL
AND DATEofcall = DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
) AS 'Lost Calls',
COUNT(acdcallinformation.idleonqueue) AS 'Total Calls',
COUNT(acdcallinformation.`ANSWERTIME`) AS 'Answered',
(
SELECT
skillinfo.skillname
FROM skillinfo
WHERE skillinfo.pkey = acdcallinformation.skillid
) AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM `acdcallinformation` acdcallinformation
WHERE DATEOFCALL = DATE(NOW())
GROUP BY skill;
Finally, I think you can handle your second query with a JOIN
SELECT
IFNULL(
(SELECT COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`) FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL
AND DATEofcall = DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
), 0) AS 'Lost Calls',
IFNULL(COUNT(acdcallinformation.idleonqueue), 0) AS 'Total Calls',
IFNULL(COUNT(acdcallinformation.`ANSWERTIME`),0) AS 'Answered',
skillinfo.skillname AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM `acdcallinformation` acdcallinformation
INNER JOIN skillinfo ON skillinfo.pkey = acdcallinformation.skillid
WHERE DATEOFCALL = DATE(NOW())
GROUP BY skill;
Try this query. The whole query is just a guess but it would be batter if you provided some data. Also i have used id as primary key you need to replace it with your own key. Avoid using subqueries instead use joins they are much faster. Here is the query.
SELECT
IF(l.LDifference IS NULL,0,r.RDifference) AS 'Lost Calls',
IF(COUNT(acdcallinformation.idleonqueue) IS NULL , 0 , COUNT(acdcallinformation.idleonqueue))AS 'Total Calls',
IF(COUNT(acdcallinformation.`ANSWERTIME`) IS NULL,0,COUNT(acdcallinformation.`ANSWERTIME`))AS 'Answered',
(SELECT skillinfo.skillname FROM skillinfo WHERE skillinfo.pkey = acdcallinformation.skillid) AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(a.answertime)- TIME_TO_SEC(a.firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(a.IDLEONQUEUE) - TIME_TO_SEC(a.answertime))) AS 'Average Talk Time'
FROM acdcallinformation as a
INNER JOIN(
SELECT
(COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`)) as `LDifference`
FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL AND DATEofcall = DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
) as l ON l.id = a.id
INNER JOIN(
SELECT (COUNT(ag.`PKEY`) - COUNT(ag.`ANSWERTIME`)) as `RDifference`
FROM acdcallinformation ag
WHERE (ag.`COMPLETED`) = 1 AND answertime IS NULL AND DATEofcall= DATE(NOW()) AND ag.skillid = acdcallinformation.skillid
) as r ON r.id = a.id
WHERE a.DATEOFCALL = DATE(NOW())
GROUP BY skill;
Try This.
Use INNER JOIN, IF() and try to avoid unnecessary subqueries.
SELECT IFNULL(ag.skillcount, 0) AS 'Lost Calls', COUNT(info.idleonqueue) AS 'Total Calls',
COUNT(info.ANSWERTIME) AS 'Answered', si.skillname AS Skill,
SEC_TO_TIME(AVG(TIME_TO_SEC(answertime)- TIME_TO_SEC(firstringonqueue))) AS 'Average Answer Time',
SEC_TO_TIME(AVG(TIME_TO_SEC(IDLEONQUEUE) - TIME_TO_SEC(answertime))) AS 'Average Talk Time'
FROM acdcallinformation AS info
INNER JOIN (
SELECT skillid, COUNT(PKEY)-COUNT(ANSWERTIME) skillcount
FROM acdcallinformation
WHERE COMPLETED = 1 AND DATEofcall = DATE(NOW()) AND answertime IS NULL
) ag ON ag.skillid = info.skillid
INNER JOIN skillinfo si ON si.pkey = info.skillid
WHERE DATEOFCALL = DATE(NOW())
GROUP BY si.skillname;

Is it possible to use a named select in the where clause?

I have a semi-complicated select statement that's building a custom "column" in a query, and the results need to be filtered by the results of this column. Is there some way to refer to this column in a predicate? You'll see what I would like to do commented out in the where clause, filtering on 'On Sale'.
select
p.prod_id,
case
when p.subtitle is null then p.title
else concat(p.title, ': ', p.subtitle)
end as 'Title',
p.issue as 'Issue',
e.abbrv as 'Editor',
p.jobnum as 'Job Number',
p.price as 'Price',
ship.due_date as 'Ship Date',
case
when pi.onsale_minus_ship_date is not null then ship.due_date + interval pi.onsale_minus_ship_date day
else
case
when prs.days_for_shipping != 0 then ship.due_date + interval prs.days_for_shipping day
else ship.due_date + interval 7 day
end
end as 'On Sale',
sale.due_date as 'Bookstore On Sale'
from products p
join schedules ship on ship.prod_id = p.prod_id and ship.milestone = 49
left join schedules sale on sale.prod_id = p.prod_id and sale.milestone = 647
left join editors e on find_in_set(e.id, p.editor)
left join printing_info pi on pi.prod_id = p.prod_id
left join printers prs on prs.id = pi.printer
where p.prod_type in (2, 3, 5, 6) -- physical, non comics (trades, hc, etc.)
--and 'On Sale' >= '$start_date' + interval 2 month
--and 'On Sale' <= '$end_date' + interval 2 month
order by ship.due_date asc, p.title asc
You can do your filtering in the HAVING clause - unfortunately, you can't refer to column aliases in the WHERE clause.
HAVING `On Sale` >= '$start_date' + interval 2 month
AND `On Sale` <= '$end_date' + interval 2 month
http://dev.mysql.com/doc/refman/5.0/en/problems-with-alias.html