decreasing running time (select query executing time)
even query is not working
it is reducing code line
there are 80 tables
select
(ant_return_loss_pass='pass')+(ant_cross_isolation_pass='pass') as pass_count,
(ant_return_loss_pass='fail')+(ant_cross_isolation_pass='fail') as fail_count,
(ant_return_loss_pass='') +(ant_cross_isolation_pass='') as blank_count
from
(
select A.serial_no,
A.pass_fail as ant_return_loss_pass
from ant_return_loss A,
(
select max(register_date) as date
from ant_return_loss
where 1=1
and serial_no >= '184500074'
and serial_no <= '184500076'
group by serial_no
) B
where 1 = 1
and A.register_date = B.date
)AA
,(
select A.serial_no,
A.pass_fail as ant_cross_isolation_pass
from ant_cross_isolation A,
(
select max(register_date) as date
from ant_cross_isolation
where 1=1
and serial_no >= '184500074'
and serial_no <= '184500076'
group by serial_no
) B
where 1 = 1
and A.register_date = B.date
)BB
where 1=1
and AA.serial_no = BB.serial_no
not working or working 600 sec
The query below uses explicit join syntax and case expressions to make you query easier to understand:
SELECT
COUNT( CASE WHEN ant_return_loss_pass = 'pass' AND
ant_cross_isolation_pass = 'pass' THEN 1 END ) AS pass_count
, COUNT( CASE WHEN ant_return_loss_pass = 'fail' AND
ant_cross_isolation_pass = 'fail' THEN 1 END ) AS fail_count
, COUNT( CASE WHEN ant_return_loss_pass = '' AND
ant_cross_isolation_pass = '' THEN 1 END ) AS blank_count
FROM (
SELECT
A.serial_no
, A.pass_fail AS ant_return_loss_pass
FROM ant_return_loss A
INNER JOIN (
SELECT MAX( register_date ) AS date
FROM ant_return_loss
WHERE serial_no >= '184500074'
AND serial_no <= '184500076'
GROUP BY serial_no
) B ON A.register_date = B.date
) AA
INNER JOIN (
SELECT
A.serial_no
, A.pass_fail AS ant_cross_isolation_pass
FROM ant_cross_isolation A
INNER JOIN (
SELECT MAX( register_date ) AS date
FROM ant_cross_isolation
WHERE serial_no >= '184500074'
AND serial_no <= '184500076'
GROUP BY serial_no
) B ON A.register_date = B.date
) BB ON AA.serial_no = BB.serial_no
To examine if this can be improved for performance however requires access to your database. For example do you indexes for ant_return_loss.serial_no or ant_cross_isolation.serial_no these will aid the where clauses of the subqueries.
Have you run any explain plans on the query? see: https://dev.mysql.com/doc/refman/5.7/en/explain.html
Note to avoid long running time you can use explain on separated portions of the overall query, look for indexes that may assist: e.g.
explain
SELECT MAX( register_date ) AS date
FROM ant_return_loss
WHERE serial_no >= '184500074'
AND serial_no <= '184500076'
GROUP BY serial_no
then:
explain
SELECT
A.serial_no
, A.pass_fail AS ant_return_loss_pass
FROM ant_return_loss A
INNER JOIN (
SELECT MAX( register_date ) AS date
FROM ant_return_loss
WHERE serial_no >= '184500074'
AND serial_no <= '184500076'
GROUP BY serial_no
) B ON A.register_date = B.date
until you have examined all portions for way to improve performance.
Related
I know, this question has been asked very often but I know my error, I know how I could fix it, but I canĀ“t find the point where the error is. In my opinion, all the subqueries have different and unique names, I even gave the columns different names then the subqueries. Any help would be appreciated. Where is the point I am missing an alias?
Whenever I am trying to run this query I get the response "Every derived table must have its alias", which is an understandable error message, but I can't figure out where my error is located.
SELECT
mso.entity_id,
GROUP_CONCAT(msh.comment) AS comment,
msoa.lastname,
base_grand_total,
mso.created_at,
mso.status,
marketplace_order_id AS amazon_order_id,
clvData.recurrenceRate,
clvData.avgRepRate
FROM
mag_sales_flat_order AS mso
LEFT JOIN mag_sales_flat_order_status_history AS msh ON mso.entity_id = msh.parent_id
LEFT JOIN mag_sales_flat_order_address AS msoa ON mso.entity_id = msoa.parent_id
left join (
select
cast(((cet.cec - cnt.cnc) / cst.csc) AS decimal(6, 2)) as recurrenceRate,
avg(repRate.countedOrders) AS avgRepRate
from(
Select
*,
(
select
count(customer_email) AS csc
from
mag_sales_flat_order
where
created_at between '2017-01-01'
and '2017-12-31'
) AS cst,
(
select
count(customer_email) AS cec
from
mag_sales_flat_order
where
created_at between '2017-01-01'
and '2020-12-31'
) AS cet,
(
select
count(mso_new.customer_email) AS cnc
from
(
select
*
from
mag_sales_flat_order
where
created_at between '2018-01-01'
and current_date()
) AS mso_new
left join (
select
*
from
mag_sales_flat_order
where
created_at between '2017-01-01'
and '2017-12-31'
) AS mso_old on mso_new.customer_email = mso_old.customer_email
)) AS cnt
join (
select
customer_email,
count(grand_total) as countedOrders,
sum(grand_total) as summedOrders
from
mag_sales_flat_order
group by
customer_email
) AS repRate on cl.customer_email = repRate.customer_email
) AS clvData on mso.customer_email = clvData.customer_email
WHERE
store_id IN({$store['id']})
AND (
mso.status = 'complete'
OR mso.status = 'closed'
OR mso.status = 'processing'
OR mso.status = 'exported'
OR mso.status LIKE 'pending%'
)
AND (
DATE_FORMAT(mso.created_at, '%Y-%m-%d') >= '$begin_date'
)
AND (
DATE_FORMAT(mso.created_at, '%Y-%m-%d') <= '$end_date'
)
GROUP BY
entity_id;
SELECT
mso.entity_id,
GROUP_CONCAT(msh.comment) AS comment,
msoa.lastname,
base_grand_total,
mso.created_at,
mso.status,
marketplace_order_id AS amazon_order_id,
clvData.recurrenceRate,
clvData.avgRepRate
FROM mag_sales_flat_order AS mso
LEFT JOIN mag_sales_flat_order_status_history AS msh ON mso.entity_id = msh.parent_id
LEFT JOIN mag_sales_flat_order_address AS msoa ON mso.entity_id = msoa.parent_id
LEFT JOIN
(
SELECT cast(((cet.cec - cnt.cnc) / cst.csc) AS decimal(6, 2)) as recurrenceRate, avg(repRate.countedOrders) AS avgRepRate
FROM
(
SELECT *,
(
SELECT count(customer_email) AS csc
FROM mag_sales_flat_order
WHERE created_at BETWEEN '2017-01-01' AND '2017-12-31'
) AS cst,
(
SELECT count(customer_email) AS cec
FROM mag_sales_flat_order
WHERE created_at BETWEEN '2017-01-01' AND '2020-12-31'
) AS cet,
(
SELECT count(mso_new.customer_email) AS cnc
FROM
(
SELECT *
FROM mag_sales_flat_order
WHERE created_at BETWEEN '2018-01-01' AND getdate()
) AS mso_new
LEFT JOIN
(
SELECT *
FROM mag_sales_flat_order
WHERE created_at BETWEEN '2017-01-01' AND '2017-12-31'
) AS mso_old on mso_new.customer_email = mso_old.customer_email
) AS cnt
) as cl
JOIN
(
SELECT customer_email, count(grand_total) as countedOrders, sum(grand_total) as summedOrders
FROM mag_sales_flat_order
GROUP BY customer_email
) AS repRate on cl.customer_email = repRate.customer_email
) AS clvData on mso.customer_email = clvData.customer_email
WHERE store_id IN({ $ store ['id'] })
AND
(
mso.status = 'complete'
OR mso.status = 'closed'
OR mso.status = 'processing'
OR mso.status = 'exported'
OR mso.status LIKE 'pending%'
)
AND
(
DATE_FORMAT(mso.created_at, '%Y-%m-%d') >= '$begin_date'
)
AND
(
DATE_FORMAT(mso.created_at, '%Y-%m-%d') <= '$end_date'
)
GROUP BY entity_id;
I have list table that basically contains same field on each part.
- p_ticket1_m_site_data | - p_ticket1_ticket | - p_ticket1_last_row
- p_ticket2_m_site_data | - p_ticket2_ticket | - p_ticket2_last_row
- p_ticket3_m_site_data | - p_ticket3_ticket | - p_ticket3_last_row
I can do a count on each table individually:
SELECT COUNT( * ) AS tot_sites, IFNULL( COUNT(
CASE WHEN p_ticket1_m_site_data.m_date_target = DATE( NOW( ) )
THEN 1
ELSE NULL
END ),0) AS todays_target, IFNULL( COUNT(
CASE WHEN (
p_ticket1_m_site_data.m_date_target = DATE( NOW( ) )
AND p_ticket1_ticket.t_status =9 )
THEN 1
ELSE NULL
END ),0
) AS todays_achieve, IFNULL( COUNT(
CASE WHEN p_ticket1_ticket.t_status =9
THEN 1
ELSE NULL
END ),0 ) AS tot_in
FROM p_ticket1_m_site_data
LEFT JOIN p_ticket1_last_row ON p_ticket1_last_row.t_m_id = p_ticket1_m_site_data.m_id
AND p_ticket1_last_row.t_req_type = '04_int_finish_ack'
LEFT JOIN p_ticket1_ticket ON p_ticket1_ticket.t_id = p_ticket1_last_row.t_id
WHERE p_ticket1_m_site_data.m_status =1
What should i do if i want to count all total sites from ticket1, ticket2, ticket3 ?
Please help me guys, thanks . . .
Example use UNION ALL:
I just using UNION ALL in my code above for ticket1 and ticket2, but its not what i want.
My expectation output is count all the ticket tables, so the view is tot_sites (from all ticket), todays_target(from all ticket), todays_achieve(from all ticket), and tot_in(from all ticket)
If you are sure that your tables have the same columns, you should use UNION ALL with CTE
WITH CTE AS (
SELECT *
FROM p_ticket1_m_site_data
UNION ALL
SELECT *
FROM p_ticket2_m_site_data
UNION ALL
...
)
SELECT COUNT(*), ...
FROM CTE
WHERE CTE.m_status = 1
CTE
UNION ALL
You can union the three sets of tables in a sub query and then do your counts in the main query , something like this in principal
SELECT COUNT( * ) AS tot_sites, IFNULL( COUNT(
CASE WHEN m_date_target = DATE( NOW( ) )
THEN 1
ELSE NULL
END ),0) AS todays_target, IFNULL( COUNT(
CASE WHEN (m_date_target = DATE( NOW( ) )
AND t_status =9 )
THEN 1
ELSE NULL
END ),0
) AS todays_achieve, IFNULL( COUNT(
CASE WHEN t_status =9
THEN 1
ELSE NULL
END ),0 ) AS tot_in
from
(
select *
FROM p_ticket1_m_site_data
LEFT JOIN p_ticket1_last_row ON p_ticket1_last_row.t_m_id = p_ticket1_m_site_data.m_id
AND p_ticket1_last_row.t_req_type = '04_int_finish_ack'
LEFT JOIN p_ticket1_ticket ON p_ticket1_ticket.t_id = p_ticket1_last_row.t_id
WHERE p_ticket1_m_site_data.m_status =1
union all
select *
frOM p_ticket2_m_site_data
LEFT JOIN p_ticket2_last_row ON p_ticket2_last_row.t_m_id = p_ticket2_m_site_data.m_id
AND p_ticket2_last_row.t_req_type = '04_int_finish_ack'
LEFT JOIN p_ticket2_ticket ON p_ticket2_ticket.t_id = p_ticket2_last_row.t_id
WHERE p_ticket2_m_site_data.m_status =1
union all
select *
fROM p_ticket3_m_site_data
LEFT JOIN p_ticket3_last_row ON p_ticket3_last_row.t_m_id = p_ticket3_m_site_data.m_id
AND p_ticket3_last_row.t_req_type = '04_int_finish_ack'
LEFT JOIN p_ticket3_ticket ON p_ticket3_ticket.t_id = p_ticket3_last_row.t_id
WHERE p_ticket3_m_site_data.m_status =1
) j;
Which could be tidied up. If this doesn't work for you please add sample data and expected output for your 3 tables as text to the question and I will review.
I have the following complex query that is giving me an error
Operand should contain 1 column(s)
Can anyone suggest what is wrong
SELECT
t.user_id AS user_id,
t.organisation_id AS organisation_id,
t.firstname AS firstname,
t.surname AS surname,
t.username AS username,
t.year_id AS year_id,
t.form_name AS form_name,
t.House AS House,
rcPoints.total AS milestoneRedeemedCodesTotal,
rcFilteredPoints.total AS redeemedCodesTotalFiltered,
(
COALESCE (rcFilteredPoints.total, 0) - COALESCE (milestoneHistory.total, 0)
) AS redeemedCodesTotalAvailableFiltered,
ABS(
FLOOR(
(
COALESCE (rcFilteredPoints.total, 0) - COALESCE (milestoneHistory.total, 0)
) / 1000
) * 1000
) AS redeemedCodesTotalTowardsMilestone,
ABS(
FLOOR(
(
COALESCE (rcFilteredPoints.total, 0) - COALESCE (milestoneHistory.total, 0)
) / 1000
)
) AS redeemedCodesMilestoneTriggers,
COALESCE (milestoneHistory.total, 0) AS historyTotal
FROM
`myuser` `t`
LEFT JOIN (
SELECT
rc.user_id AS user_id,
SUM(rc.school_points) AS total
FROM
`redeemed_codes` `rc`
INNER JOIN myuser m ON (m.user_id = rc.user_id)
WHERE
(rc.date_redeemed >= 0)
AND (m.organisation_id = 58022)
GROUP BY
rc.user_id
) AS rcPoints ON (rcPoints.user_id = t.user_id)
LEFT JOIN (
SELECT
rc.user_id AS user_id,
SUM(rc.school_points) AS total
FROM
`redeemed_codes` `rc`
INNER JOIN myuser m ON (m.user_id = rc.user_id)
WHERE
(rc.date_redeemed >= 0)
AND (m.organisation_id = 58022)
GROUP BY
rc.user_id
) AS rcFilteredPoints ON (
rcFilteredPoints.user_id = t.user_id
)
LEFT JOIN (
SELECT
mh.user_id AS user_id,
mh.milestone_id AS milestone_id,
MAX(mh.points_when_triggered) AS total
FROM
`milestone_history` `mh`
WHERE
mh.milestone_id = 13
GROUP BY
mh.user_id
) AS milestoneHistory ON (
milestoneHistory.user_id = t.user_id
)
WHERE
(
(
SELECT
COALESCE (count(*), 0)
FROM
milestone_history mha
WHERE
mha.milestone_id = 13
AND mha.user_id = t.user_id
) = 0
)
AND (t.organisation_id = 58022)
AND
(
SELECT * FROM
redeemed_codes t1
WHERE
organisation_id = 1
AND
(
SELECT
sum(school_points)
FROM
redeemed_codes t2
WHERE
t2.redeemed_code_id <= t1.redeemed_code_id
) >= 1000
ORDER BY redeemed_code_id
LIMIT 1
)
GROUP BY
t.user_id
ORDER BY
redeemedCodesMilestoneTriggers DESC
LIMIT 1
Your query might have multiple errors, but this condition in the WHERE clause is definitely suspect and would lead to that error:
AND (SELECT *
FROM redeemed_codes t1
WHERE organisation_id = 1 AND
(SELECT sum(school_points)
FROM redeemed_codes t2
WHERE t2.redeemed_code_id <= t1.redeemed_code_id
) >= 1000
ORDER BY redeemed_code_id
LIMIT 1
)
I have no idea what you are trying to do. Sometimes, the solution is simply EXISTS:
EXISTS (SELECT *
FROM redeemed_codes t1
WHERE organisation_id = 1 AND
(SELECT sum(school_points)
FROM redeemed_codes t2
WHERE t2.redeemed_code_id <= t1.redeemed_code_id
) >= 1000
)
I have a database that contains member information for a club. Each member at any time can be one of three distinct statuses (active, veteran, associate). I have it broken down into three tables. The member table, with all the member information, the status table with the status_name and status_id and a grid table which includes the member_id, status_id, date_from and date_to.
I am trying to calculate the amount of time a member has spent at each status. I am currently calculating the total time that the member has spent in the "active" status via the following query:
SELECT first_name, last_name,
(DATE_FORMAT( FROM_DAYS( SUM( DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) ) , "%Y" ) +0) as service_years
FROM member a
LEFT JOIN member_status q on a.id = q.member_id AND q.status_id = 1
GROUP BY a.id
I know that I can pull the total time that the person has been a member by leaving off the AND in the left join, however I can't figure out a way to calculate the time for each status in a single query.
My ideal result would be along the lines of:
-----------------------------------------------------------
|member_name | active_years | veteran_years | total_years |
-----------------------------------------------------------
|name | 5 | 5 | 10 |
-----------------------------------------------------------
Is there a way to accomplish what I'm looking for in a single query?
Assuming 1=active and 2=veteran, something like this should work:
SELECT first_name, last_name,
(DATE_FORMAT( FROM_DAYS( SUM( case when q.status_id = 1 then DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) else 0 end ) , "%Y" ) +0) as active_years,
(DATE_FORMAT( FROM_DAYS( SUM( case when q.status_id = 2 then DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) else 0 end ) , "%Y" ) +0) as veteran_years,
(DATE_FORMAT( FROM_DAYS( SUM( DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) ) , "%Y" ) +0) as total_years
FROM member a
LEFT JOIN member_status q on a.id = q.member_id AND q.status_id in (1,2)
GROUP BY a.id
Another option is to join the member_status table more than once.
You should be able to do something like this which uses a CASE statement to determine the status name and then calculates the total number of years based on the status:
SELECT first_name,
last_name,
CASE WHEN status_name = 'active'
then (DATE_FORMAT( FROM_DAYS( SUM( DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) ) , "%Y" ) +0) end as active_years,
CASE WHEN status_name = 'veteran'
then (DATE_FORMAT( FROM_DAYS( SUM( DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) ) , "%Y" ) +0) end as active_years,
(DATE_FORMAT( FROM_DAYS( SUM( DATEDIFF( IFNULL( q.date_to, NOW() ) , q.date_from ) ) ) , "%Y" ) +0) as total_years,
FROM member a
LEFT JOIN member_status q
on a.id = q.member_id
AND q.status_id = 1
GROUP BY a.id, a.first_name, a.last_name
if you post some sample data it will be easier to determine the proper query
I am actually stuck in merging the result of this two queries:
first query:
SELECT c.code, c.name, pc.sku, pc.cat_code, pp.title
FROM `cat_parent` cp, cat c, prod_cat pc, products pp
WHERE c.code = cp.cat_code
AND cp.cat_code = pc.cat_code
AND pp.sku = pc.sku
AND cp.parent_code = 01110
AND hide =0
The result I get is:
Second query:
SELECT `sku` , `update_date` , `description` , count( * ) AS total_sold
FROM `orderline`
WHERE `update_date` >= ( DATE_ADD(CURDATE( ) , INTERVAL -14 DAY ) )
AND `update_date` <= ( DATE_ADD(CURDATE( ) , INTERVAL -7 DAY ) )
GROUP BY left( sku, 7 )
ORDER BY total_sold DESC
The result:
The question I want to ask that how can I get the result by filtering the sku available in both tables.
Just bit confused on that part....any ideas will be appreciated.
This is only part of the data. there is heaps of data. Yes, I want to merge the both tables and want to find the common sku available in both tables.
My expected result will be sku, title, total sold.
Thanks, anyway I managed to get around to get the result.
My final query:
SELECT * FROM (
SELECT sku , update_date , description FROM orderline WHERE
update_date >= '2012-03-06' AND update_date <= '2012-03-07' )g
JOIN (
SELECT c.code, c.name, pc.sku, pc.cat_code FROM cat_parent cp, cat
c, prod_cat pc, products pp WHERE c.code = cp.cat_code AND cp.cat_code
= pc.cat_code AND pp.sku = pc.sku AND cp.parent_code =01110 AND hide =0 )p ON left( g.sku, 7 ) = left( p.sku, 7 )
Something like this -
SELECT
`c`.`code`, `c`.`name`, `pc`.`sku`, `pc`.`cat_code`, `pp.title`,
`ol`.`sku`, `ol`.`update_date`, `ol`.`description`, COUNT(*) AS `total_sold`
FROM `cat_parent` `cp`
INNER JOIN `cat` `c`
ON `c`.`code` = `cp`.`cat_code`
INNER JOIN `prod_cat` `pc`
ON `cp`.`cat_code` = `pc`.`cat_code`
INNER JOIN `products` `pp`
ON `pp`.`sku` = `pc`.`sku`
INNER JOIN `orderline` `ol`
ON LEFT(`pc`.`sku`, 7) = LEFT(`ol`.`sku`, 7)
WHERE `cp`.`parent_code` = 01110
AND `hide` = 0
AND `ol`.`update_date` >= ( DATE_ADD(CURDATE( ) , INTERVAL -14 DAY ) )
AND `ol`.`update_date` <= ( DATE_ADD(CURDATE( ) , INTERVAL -7 DAY ) )
GROUP BY left( `ol`.`sku`, 7 )
ORDER BY `total_sold` DESC