Order Clause on query took too much load time MySQL - mysql

I am stuck at a point where I have millions of records and required different joins for the same. Also there are some tricky part for the order clause. My query performs fast result if I'll not apply any ordering. But while applying order clause it takes too much time to get result.
Without Order clause it results in 5-6 seconds.
While applying Order Clause it results in 40-45 second
SELECT
forms_values.id,
CASE
WHEN forms_values.appointment_type = 2
AND user_patient_assinged_to_doctor.start_time IS NOT NULL
THEN
CASE
WHEN patient_responded_tags_logs.tag_set_at IS NOT NULL
THEN
CASE
WHEN UNIX_TIMESTAMP(
CONVERT_TZ(
patient_responded_tags_logs.tag_set_at,
"+00:00",
"-06:00"
)
) > UNIX_TIMESTAMP(
CONVERT_TZ(
STR_TO_DATE(
CONCAT(
user_patient_assinged_to_doctor.date,
" ",
user_patient_assinged_to_doctor.start_time
),
"%Y-%m-%d %h:%i %p"
),
"+00:00",
"-06:00"
)
)
THEN UNIX_TIMESTAMP(
CONVERT_TZ(
patient_responded_tags_logs.tag_set_at,
"+00:00",
"-06:00"
)
)
ELSE UNIX_TIMESTAMP(
CONVERT_TZ(
STR_TO_DATE(
CONCAT(
user_patient_assinged_to_doctor.date,
" ",
user_patient_assinged_to_doctor.start_time
),
"%Y-%m-%d %h:%i %p"
),
"+00:00",
"-06:00"
)
)
END
ELSE UNIX_TIMESTAMP(
CONVERT_TZ(
STR_TO_DATE(
CONCAT(
user_patient_assinged_to_doctor.date,
" ",
user_patient_assinged_to_doctor.start_time
),
"%Y-%m-%d %h:%i %p"
),
"+00:00",
"-06:00"
)
)
END
ELSE
CASE
WHEN patient_responded_tags_logs.tag_set_at IS NOT NULL
THEN
CASE
WHEN UNIX_TIMESTAMP(
CONVERT_TZ(
patient_responded_tags_logs.tag_set_at,
"+00:00",
"-06:00"
)
) > UNIX_TIMESTAMP(forms_values.created_at)
THEN UNIX_TIMESTAMP(
CONVERT_TZ(
patient_responded_tags_logs.tag_set_at,
"+00:00",
"-06:00"
)
)
ELSE UNIX_TIMESTAMP(forms_values.created_at)
END
ELSE UNIX_TIMESTAMP(forms_values.created_at)
END
END AS "consultation_date_time_ordering",
CASE
WHEN forms_values.appointment_type = 2
AND user_patient_assinged_to_doctor.start_time IS NOT NULL
THEN UNIX_TIMESTAMP(
CONVERT_TZ(
STR_TO_DATE(
CONCAT(
user_patient_assinged_to_doctor.date,
" ",
user_patient_assinged_to_doctor.start_time
),
"%Y-%m-%d %h:%i %p"
),
"+00:00",
"-06:00"
)
)
ELSE UNIX_TIMESTAMP(forms_values.created_at)
END AS "consultation_date_time" ,
CASE
WHEN forms_values.is_postpone = '1'
OR forms_values.is_completed = '8'
THEN
CASE
WHEN UNIX_TIMESTAMP(
CONVERT_TZ(
STR_TO_DATE(
CONCAT(UTC_DATE(), ' ', UTC_TIME()),
'%Y-%m-%d %h:%i:%s'
),
'+00:00',
'-06:00'
)
) < UNIX_TIMESTAMP(
my_list_postpone.postponed_date
)
THEN 0
ELSE 1
END
ELSE 1
END AS "postponed_consultation_ordering"
FROM
`forms_values`
LEFT JOIN `forms_values_completed_status_details`
ON `forms_values_completed_status_details`.`form_value_id` = `forms_values`.`id`
/*INNER JOIN `users`
ON `users`.`id` = `forms_values`.`patient_id`
LEFT JOIN `users` AS `doctors`
ON `doctors`.`id` = `forms_values`.`doctor_id`*/
LEFT JOIN `user_patient_assinged_to_doctor`
ON `user_patient_assinged_to_doctor`.`form_value_id` = `forms_values`.`id`
INNER JOIN `states_countries`
ON `forms_values`.`state` = `states_countries`.`id`
LEFT JOIN `user_payment_history`
ON `user_payment_history`.`form_value_id` = `forms_values`.`id`
LEFT JOIN `emailed_tags_logs`
ON `emailed_tags_logs`.`form_value_id` = `forms_values`.`id`
AND `emailed_tags_logs`.`id` =
(SELECT
emailed_tags_logs.id
FROM
emailed_tags_logs
WHERE emailed_tags_logs.form_value_id = forms_values.id
AND emailed_tags_logs.id =
(SELECT
emailed_tags_logs1.id AS emtid
FROM
emailed_tags_logs AS emailed_tags_logs1
WHERE emailed_tags_logs1.form_value_id = forms_values.id
ORDER BY emailed_tags_logs1.created_at DESC
LIMIT 1)
AND emailed_tags_logs.status IN (1, 3)
AND emailed_tags_logs.is_pt_responded = "0"
ORDER BY emailed_tags_logs.created_at DESC
LIMIT 1)
LEFT JOIN `my_list_assign_doctor`
ON `my_list_assign_doctor`.`form_value_id` = `forms_values`.`id`
AND `my_list_assign_doctor`.`id` =
(SELECT
my_list_assign_doctor.id
FROM
my_list_assign_doctor
WHERE my_list_assign_doctor.form_value_id = forms_values.id
AND my_list_assign_doctor.status IN (1, 2)
AND my_list_assign_doctor.prior_type = "others"
ORDER BY my_list_assign_doctor.created_at DESC
LIMIT 1)
LEFT JOIN `my_list_assign_doctor` AS `my_list_postpone`
ON `my_list_postpone`.`form_value_id` = `forms_values`.`id`
AND `forms_values`.`is_postpone` IN ('1', '2')
AND `my_list_postpone`.`id` =
(SELECT
my_list_assign_doctor.id
FROM
my_list_assign_doctor
WHERE my_list_assign_doctor.form_value_id = forms_values.id
AND my_list_assign_doctor.prior_type = "postpone"
ORDER BY my_list_assign_doctor.created_at DESC
LIMIT 1)
LEFT JOIN `users` AS `partner`
ON `user_payment_history`.`std_partner_id` = `partner`.`id`
LEFT JOIN `patient_responded_tags_logs`
ON `patient_responded_tags_logs`.`form_value_id` = `forms_values`.`id`
AND `patient_responded_tags_logs`.`status` = '1'
LEFT JOIN `user_subscriptions`
ON `user_subscriptions`.`user_payment_history_id` = `user_payment_history`.`id`
AND `user_payment_history`.`form_value_id` = `forms_values`.`id`
ORDER BY
postponed_consultation_ordering DESC,
`consultation_date_time` DESC
LIMIT 10 OFFSET 0
Note: All joins are important, and fields are removed from select query for some concerns.
Explain summary

The problem is the combination of LIMIT and ORDER BY.
Without the ORDER BY the query will stop as soon as the first ten random rows are selected. With the order by the query must gather all possible rows then sort them in order then only return the first 10.
There is really no way to make this any faster given that 'postponed_consultation_datetime' is a calculated field.

Some of these composite indexes may be helpful.
user_patient_assinged_to_doctor: INDEX(form_value_id, start_time, date)
patient_responded_tags_logs: INDEX(form_value_id, tag_set_at, status)
my_list_postpone: INDEX(form_value_id, postponed_date, id)
forms_values_completed_status_details: INDEX(form_value_id)
user_payment_history: INDEX(form_value_id, std_partner_id, id)
user_subscriptions: INDEX(user_payment_history_id)
emailed_tags_logs: INDEX(form_value_id, created_at, id)
emailed_tags_logs: INDEX(form_value_id, id, status, is_pt_responded, created_at)
my_list_assign_doctor: INDEX(form_value_id, status, prior_type, created_at, id)
my_list_assign_doctor: INDEX(form_value_id, prior_type, created_at, id)
my_list_assign_doctor: INDEX(form_value_id, id, status, prior_type, created_at)
Don't use LEFT JOIN when you mean INNER JOIN.
FALSE is 0; TRUE is anything else. See if you can simplify some of the CASE statements:
CASE WHEN boolean THEN 1 ELSE 0
is identical to
boolean
Similarly:
CASE WHEN boolean THEN 0 ELSE 1
can probably be replaced by
With proper use of TIMESTAMP versus DATETIME, you can possibly get rid of all the calls to CONVERT_TZ.
NOT boolean
However, this may help the most... Turn the query inside out. See what the minimal effort is to find the LIMIT 10 ids. Hopefully, you only need to look at one, or a small number of, the tables. Then use that as a subquery ("derived table") and then reach for the rest of the columns.

Related

What kind of query optimization can be done on this query?

I'm listing out orders data based on this query. This query basically pulls the recurring orders data from the table. I'm also using some dropdown and a input field to search / filter query results.
SELECT
orders.id,
parent_id,
(
SELECT
COUNT(*)
FROM
orders o
WHERE
o.parent_id = orders.id
) AS recurring_order_count,
shopify_order_type,
shopify_order_id,
shopify_order_customer_ID,
coupon_code AS coupon,
FORMAT(shopify_order_total_price, 2) AS shopify_order_total_price,
FORMAT(
shopify_order_subtotal_price,
2
) AS shopify_order_subtotal_price,
FORMAT(
shopify_order_total_line_items_price,
2
) AS shopify_order_total_line_items_price,
FORMAT(commission_amount, 2) AS commission_amount,
(
CASE WHEN is_paid = 0 THEN 'No' WHEN is_paid = 1 THEN 'Yes' ELSE 'Rejected'
END
) AS is_paid,
(
CASE WHEN is_invoice_generated = 1 THEN 'Pending' ELSE 'Invoice Generated'
END
) AS is_invoice_generated,
DATE_FORMAT(
shopify_order_created_at,
'%m-%d-%Y'
) AS shopify_order_created_at,
(
CASE WHEN is_paused = 0 THEN 'Running' ELSE 'Paused'
END
) AS is_paused,
DATE_FORMAT(
shopify_recurring_date,
'%m-%d-%Y'
) AS shopify_recurring_date
FROM
`orders`
WHERE
coupon_code LIKE '%GERALD8314%' OR shopify_order_id LIKE '%GERALD8314%' OR(
CASE WHEN is_paid = 0 THEN 'No' WHEN is_paid = 1 THEN 'Yes' ELSE 'Rejected'
END
) LIKE '%GERALD8314%' OR(
CASE WHEN is_invoice_generated = 1 THEN 'Pending' ELSE 'Invoice Generated'
END
) LIKE '%GERALD8314%' OR DATE_FORMAT(
shopify_order_created_at,
'%m-%d-%Y'
) LIKE '%GERALD8314%' OR(
CASE WHEN is_paused = 0 THEN 'Running' ELSE 'Paused'
END
) LIKE '%GERALD8314%' OR DATE_FORMAT(
shopify_recurring_date,
'%m-%d-%Y'
) LIKE '%GERALD8314%' AND DATE_FORMAT(
shopify_order_created_at,
'%Y-%m-%d'
) BETWEEN ? AND ?
GROUP BY
`id`
HAVING
parent_id = 0 AND shopify_order_type = 1
ORDER BY
`id`
DESC
LIMIT 10 OFFSET 0
Is this query optimized? Is this SELECT COUNT(*) FROM orders WHERE o.parent_id = orders.id AS recurring_order_count line most expensive in terms of query execution speed? Is there anything I should take care to improve the query speed here? Please advise.
OR and LIKE with leading wildcard are terrible for performance. Consider having a FULLTEXT index across the relevant columns. If it is practical, it will be immensely faster.
WHERE coupon_code LIKE '%GERALD8314%'
OR shopify_order_id LIKE '%GERALD8314%' OR( CASE WHEN is_paid = 0 THEN 'No' WHEN is_paid = 1 THEN 'Yes' ELSE 'Rejected' END ) LIKE '%GERALD8314%' OR( CASE WHEN is_invoice_generated = 1 THEN 'Pending' ELSE 'Invoice Generated' END ) LIKE '%GERALD8314%'
OR DATE_FORMAT( shopify_order_created_at, '%m-%d-%Y' ) LIKE '%GERALD8314%' OR( CASE WHEN is_paused = 0 THEN 'Running' ELSE 'Paused' END ) LIKE '%GERALD8314%'
OR DATE_FORMAT( shopify_recurring_date, '%m-%d-%Y' ) LIKE '%GERALD8314%'
AND DATE_FORMAT( shopify_order_created_at, '%Y-%m-%d' ) BETWEEN ? AND ?
Also, there may be surprises in the results. Note that you have
a OR b OR c AND d
which is the same as
a OR b OR (c AND d)
I suspect you wanted
(a OR b OR c) AND d
I think the GROUP BY is unnecessary. And the HAVING clauses can be merged into the WHERE.
GROUP BY `id`
HAVING parent_id = 0
AND shopify_order_type = 1
ORDER BY `id` DESC
This has multiple issues:
DATE_FORMAT( shopify_order_created_at, '%Y-%m-%d' ) BETWEEN ? AND ?
BETWEEN is "inclusive". The way you have written the query, it will include the entire ending day. This may not be what you wanted.
Assuming the variable is a DATE or DATETIME, it can be simplified to
shopify_order_created_at BETWEEN ? AND ?
There may be more tips; fix these then come back for more.

complex query - look back on same table data to output results in mysql (VERY slow query)

I'm trying to optimize a query, which as the db is growing, its performance is severely lacking.
Background: we are trying to find a list of users who have taken a course and their credential is now due to be renewed (or has not renewed). In searching the query we have to have a look into the registration table (which is the same table that holds all their registration history) and find records where they have not renewed. (Each time the client takes a course they have a registration record added.) The query I'm wanting to optimize looks to see if they've (client) taken the same course type on a date/time after the last class (of same type) they took. If there is no record it should result row(s) that they didn't renew their course. it sounds easy, but, as you know, when you're in the heat of writing a query it gets very complex--and even more so once the db has grown to be so large that it takes almost 5-6 minutes to find the data. So, I'm asking for help on how I can optimize the efforts of my predecessor, below.
Here is the query, thus far (don't laugh, it wasn't started by me--I took over the project).
I have no clue where to begin with optimizing this MySQL. I think it needs to have select statements within the JOINS, but I'm at your mercy to direct me as to where to start! (I"m not a db guy, but offered to take a look and see where we can fix this).
Thanks a million for reading.
Lee
SELECT
r.GUID AS `A/C #`,
concat( a.AttendeeLastName, ', ', a.AttendeeFirstName ) AS Full Name (Last, First),
r.CourseExpirationDateFull AS `Exp Date`,
mtype_master_abbrev AS Course,
a.EmailName AS Email,
r.EventID,
r.EventTypeMasterID,
m.type_master_name,
IF( ( r.CourseExpirationDateFull < curdate( ) ), 'Expired', 'Valid' ) AS Status,
e.StartDateTime,
( to_days( curdate( ) ) - to_days( r.ExpNoticeSent ) ) AS Last Notice,
r.AttendeeID,
a.AttendeeCredentials,
r.RegistrationID,
r.RenewedExternalYYYY,
r.ExpNoticeSent,
q.RenewedRegID,
rs.reg_status_name AS `Reg Status`,
( to_days( r.CourseExpirationDateFull ) - to_days( curdate( ) ) ) AS Days2Exp,
a.flgReturnEmail,
a.flgSendEmail,
r.reg_type_ID,
a._usr_flg_do_not_call,
a.flgPrintLetter
e.EventTypeMasterID AS MasterID,
c.Last: yy-mm-dd - by - topic AS LastComm,
r.reg_renewal_status_id
FROM
vjgzuqrr_wtsql.registration r LEFT JOIN vjgzuqrr_wtsql.events ON ( r.EventID = events.EventID ) LEFT JOIN
vjgzuqrr_wtsql.attendees a ON a.ID = r.GUID LEFT JOIN
vjgzuqrr_wtsql.tbl_crs_type_master m ON r.EventTypeMasterID = m.ID_crs_type_master LEFT JOIN
vjgzuqrr_wtsql.qryrenreg q ON r.RegistrationID = q.OrigRegID LEFT JOIN
vjgzuqrr_wtsql.tbl_reg_status rs ON rs.ID_reg_status = r.RegistrationStatus LEFT JOIN
vjgzuqrr_wtsql.v_last_contact c ON c.registrationid = r.RegistrationID
WHERE
r.Role = 1
AND r.reg_type_ID IN ( 1, 2 )
AND r.CompletionStatus IN ( 9, 8 )
AND r.r IN ( 1, 14, 9 )
AND ( r.EventTypeMasterID IS NOT NULL OR r.EventTypeMasterID = 17 )
AND r.flgDelete = 0
AND r.flgTest = 0
AND e.flgDelete = 0
AND e.flgTestCourse = 0
AND e.flgDelete = 0
AND a.flgTest = 0
AND isnull( q.RenewedRegID )
AND a.flgReturnEmail = 0
AND m.type_master_abbrev NOT IN ( 'EKGPHARM', 'IVCERT', 'sem', 'fam&friends', 'cccc' )
Edit to include Explain:
Sorry im a bit slow, mysql,
This does not speed anything up ( i think, but it may help a bit), but it should help in reading it in a non-mindbreaking way. (hopefully this will also help others look at it.)
SELECT
r.GUID AS `A/C #`,
concat( a.AttendeeLastName, ', ', a.AttendeeFirstName ) AS Full Name (Last, First),
r.CourseExpirationDateFull AS `Exp Date`,
mtype_master_abbrev AS Course,
a.EmailName AS Email,
r.EventID,
r.EventTypeMasterID,
m.type_master_name,
IF( ( r.CourseExpirationDateFull < curdate( ) ), 'Expired', 'Valid' ) AS Status,
e.StartDateTime,
( to_days( curdate( ) ) - to_days( r.ExpNoticeSent ) ) AS Last Notice,
r.AttendeeID,
a.AttendeeCredentials,
r.RegistrationID,
r.RenewedExternalYYYY,
r.ExpNoticeSent,
q.RenewedRegID,
rs.reg_status_name AS `Reg Status`,
( to_days( r.CourseExpirationDateFull ) - to_days( curdate( ) ) ) AS Days2Exp,
a.flgReturnEmail,
a.flgSendEmail,
r.reg_type_ID,
a._usr_flg_do_not_call,
a.flgPrintLetter
e.EventTypeMasterID AS MasterID,
c.Last: yy-mm-dd - by - topic AS LastComm,
r.reg_renewal_status_id
FROM
vjgzuqrr_wtsql.registration r LEFT JOIN
vjgzuqrr_wtsql.events e ON r.EventID = e.EventID LEFT JOIN
vjgzuqrr_wtsql.attendees a ON a.ID = r.GUID LEFT JOIN
vjgzuqrr_wtsql.tbl_crs_type_master m ON r.EventTypeMasterID = m.ID_crs_type_master LEFT JOIN
vjgzuqrr_wtsql.qryrenreg q ON r.RegistrationID = q.OrigRegID LEFT JOIN
vjgzuqrr_wtsql.tbl_reg_status rs ON rs.ID_reg_status = r.RegistrationStatus LEFT JOIN
vjgzuqrr_wtsql.v_last_contact c ON c.registrationid = r.RegistrationID
WHERE
r.Role = 1
AND r.reg_type_ID IN ( 1, 2 )
AND r.CompletionStatus IN ( 9, 8 )
AND r.r IN ( 1, 14, 9 )
AND ( r.EventTypeMasterID IS NOT NULL OR r.EventTypeMasterID = 17 )
AND r.flgDelete = 0
AND r.flgTest = 0
AND e.flgDelete = 0
AND e.flgTestCourse = 0
AND e.flgDelete = 0
AND a.flgTest = 0
AND isnull( q.RenewedRegID )
AND a.flgReturnEmail = 0
AND m.type_master_abbrev NOT IN ( 'EKGPHARM', 'IVCERT', 'sem', 'fam&friends', 'cccc' )

Different results from Identical databases

I'm having an issue where my live database (MariaDB) has the exact same data as my local(MySQL) but the following query is returning the same results but in a different order (I know im not the best at SQL so I'll apologise in advance):
SELECT
`products`.*
, CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) AS `order_date`
, `category_product`.`category_id` AS `pivot_category_id`
, `category_product`.`product_id` AS `pivot_product_id`
, `count_activate`.`active_count`
, IF( `count_activate`.`product_id` > 0, 0, 1 ) AS coming_soon
FROM
`products`
INNER JOIN
`category_product`
ON
`products`.`id` = `category_product`.`product_id`
LEFT JOIN
(
SELECT
inventory.*
FROM
inventory
INNER JOIN
`booking_inventory`
ON
`inventory`.`id` = `booking_inventory`.`inventory_id`
WHERE
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) > NOW()
ORDER BY
DATE( CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) )
)
AS
inventory
ON
`products`.`id` = `inventory`.`product_id`
INNER JOIN
`booking_inventory`
ON
`inventory`.`id` = `booking_inventory`.`inventory_id`
LEFT JOIN
(
SELECT
COUNT(inventory.id) AS active_count
, product_id
FROM
inventory
INNER JOIN
`booking_inventory`
ON
`inventory`.`id` = `booking_inventory`.`inventory_id`
WHERE
status_id = 1
AND
(
stock > 0
OR stock = -1
)
AND
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) > NOW()
GROUP BY
product_id
)
AS
count_activate
ON
`count_activate`.`product_id` = `products`.`id`
WHERE
`category_product`.`category_id` = 2
AND EXISTS
(
SELECT
*
FROM
`sites`
INNER JOIN
`product_site`
ON
`sites`.`id` = `product_site`.`site_id`
WHERE
`product_site`.`product_id` = `products`.`id`
AND
`status_id` = 1
AND
`site_id` = 1
)
AND
`products`.`status_id` = 1
AND
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) > NOW()
GROUP BY
`products`.`id`
ORDER BY
`coming_soon` ASC
, `order_date` ASC
LIMIT 100
OFFSET 0
can anyone tell me whats causing this?
regards
(left id External right is Local)
EDIT
Thanks for the daft comments below and the down vote, very helpful.... After some digging, I have found the cause yet not the answer. In the second JOIN (inventory) the date ordering isn't returning the same results. If I order by the inventory id, price, SKU I get the same results across local and external data but not using the date... would anyone know why?
regards
The problem was down to the version/dbengine. The first left join has an order by in it, which I didn't realise didn't keep its order once used by the parent (depending on version/dbengine).
One way to overcome this is by setting a limit of 18446744073709551615 which forces the results to be stored in a temp table (or something, i know not what I speak!).
the other issue was inner join further down the query which forced to table to be reordered.
SELECT
IF( `counter`.`product_id` > 0, 0, 1 ) AS coming_soon,
bd.skill_level,
counter.active_count,
p.*
FROM
(
SELECT
p.*,
booking_inventory.inventory_id,
category_product.category_id,
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) as date
FROM
booking_inventory
JOIN
inventory
ON
inventory.id = booking_inventory.inventory_id
LEFT JOIN
products AS p
ON
p.id = inventory.product_id
INNER JOIN
`category_product`
ON
`p`.`id` = `category_product`.`product_id`
WHERE
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) > NOW()
AND
`category_product`.`category_id` = 2
ORDER BY
date
LIMIT
18446744073709551615
)
AS
p
LEFT JOIN
booking_data AS bd
ON
p.id = bd.product_id
LEFT JOIN
(
SELECT
COUNT(`inventory`.`id`) AS `active_count`,
`inventory`.`product_id`
FROM
`inventory`
INNER JOIN
`booking_inventory`
ON
`inventory`.`id` = `booking_inventory`.`inventory_id`
WHERE
`inventory`.`status_id` = 1
AND
(
`inventory`.`stock` > 0
OR
`inventory`.`stock` = -1
)
AND
CONCAT( `booking_inventory`.`year`, '-', LPAD( `booking_inventory`.`month`, 2, '00' ), '-', LPAD( `booking_inventory`.`day`, 2, '00' ) ) > NOW()
GROUP BY
`inventory`.`product_id`
)
AS
counter
ON
`counter`.`product_id` = `p`.`id`
WHERE
EXISTS
(
SELECT
*
FROM
`sites`
INNER JOIN
`product_site`
ON
`sites`.`id` = `product_site`.`site_id`
WHERE
`product_site`.`product_id` = `p`.`id`
AND
`status_id` = 1
AND
`site_id` = 1
)
GROUP BY
p.id
ORDER BY
coming_soon,
p.date,
p.name

MySQL query take more time to execution

SELECT
gst_journal.*,
salesmain.TransactionNo
FROM
`gst_journal`
LEFT JOIN salesmain
ON (
gst_journal.docNo = salesmain.InvoiceNo
AND gst_journal.Source = salesmain.Source
)
WHERE (
MONTH(salesmain.TDate) = '10'
AND YEAR(salesmain.TDate) = '2013'
AND salesmain.TDate BETWEEN STR_TO_DATE('2013-10-01', '%Y-%m-%d')
AND STR_TO_DATE('2013-10-31', '%Y-%m-%d')
AND (
(
gst_journal.inOutTax = 'OUT'
AND gst_journal.taxType IN ('SR', 'GST')
AND gst_journal.Source IN ('AR', 'NR', 'BR', 'PR', 'JV', 'CR')
)
)
)
OR (
MONTH(gst_journal.TDate) = '10'
AND YEAR(gst_journal.TDate) = '2013'
AND (
gst_journal.TDate BETWEEN STR_TO_DATE('2013-10-01', '%Y-%m-%d')
AND STR_TO_DATE('2013-10-31', '%Y-%m-%d')
AND (
gst_journal.taxType = 'SR'
AND gst_journal.Source IN ('BR')
)
)
)
ORDER BY gst_journal.Tdate,
salesmain.TDate ;
this query run properly and records give correct but it take to time run.
Any one help to optimize time query.
Thanks

MYSQL Query works for current week not next

SELECT a.agent, a.talktime, a.percentclosed,COALESCE(COUNT(b.dealamount),0),COALESCE(SUM(b.dealamount),0) , b.dealdate
FROM closers a
LEFT JOIN deals b ON a.agent = b.agent
WHERE b.dealdate IS NULL OR YEARWEEK( b.dealdate ) = YEARWEEK( NOW( ) )
GROUP BY a.agent
ORDER BY COALESCE( SUM( b.dealamount ) , 0 ) DESC
Can anybody help me fix this query i know its messy but im new to this,
This works fine for the current week but if i add +1 to simulate a future week everybody who has a deal the week before does not show,
Thanks,
John,
IMAGE OF QUERY'S
WEEKOFYEAR is not good in this case because it will wrap at year's end. You should use YEARWEEK().
WHERE b.dealdate IS NULL OR YEARWEEK( b.dealdate ) = YEARWEEK( NOW( ) ) +1
Got it to work!,
SELECT a.agent, a.talktime, a.percentclosed, COALESCE( COUNT( b.dealamount ) , 0 ) ,COALESCE( SUM( b.dealamount ) , 0 ) , b.dealdate
FROM closers a
LEFT JOIN deals b ON a.agent = b.agent
AND WEEKOFYEAR( b.dealdate ) = WEEKOFYEAR( NOW( ) )
WHERE b.dealdate IS NULL
OR WEEKOFYEAR( b.dealdate ) = WEEKOFYEAR( NOW( ) )
GROUP BY a.agent
ORDER BY COALESCE( SUM( b.dealamount ) , 0 ) DESC
LIMIT 0 , 30
WHERE b.dealdate IS NULL OR WEEKOFYEAR( b.dealdate ) = WEEKOFYEAR( date_add(NOW( ), interval 1 week))
use the interval feature of mysql, and the date_add or date_sub function
Reference