How to optimize this heavy MySQL query? - mysql

I need to optimize a MySQL query which takes a lot of time to load.
Here it is :
SELECT
p.id,
UNIX_TIMESTAMP(p.last_answer_date) AS last_answer_date_timestamp,
p.sender_id,
p.recipient_id,
p.is_read_sender,
p.last_answer_user_id,
p.is_read_recipient,
(SELECT m.read FROM pm_message m WHERE m.conv_id = p.id AND m.user_id != $user_id ORDER BY m.date DESC LIMIT 1) AS read_status,
(SELECT m.content FROM pm_message m WHERE m.conv_id = p.id ORDER BY m.date DESC LIMIT 1) AS last_message,
(SELECT u.username FROM user u WHERE (u.id = p.sender_id OR u.id = p.recipient_id) AND u.id != $user_id LIMIT 1) AS from_username,
(SELECT u.id FROM user u WHERE (u.id = p.sender_id OR u.id = p.recipient_id) AND u.id != $user_id LIMIT 1) AS from_userid,
(SELECT ui.gender FROM user_info ui WHERE (ui.user_id = p.sender_id OR ui.user_id = p.recipient_id) AND ui.user_id != $user_id LIMIT 1) AS from_gender,
(SELECT ph.thumb_url FROM photo ph, user_info ui WHERE ui.main_photo = ph.id AND (ph.user_id = p.sender_id OR ph.user_id = p.recipient_id) AND ph.user_id != $user_id LIMIT 1) AS from_thumb_url
FROM pm_conv p
WHERE p.sender_id = $user_id OR p.recipient_id = $user_id
ORDER BY p.last_answer_date DESC LIMIT 25;
This query gets me the result I want but it's really slow... And I think that the nested selects is the reason why this query is so slow.
Here are the tables structures for this query :
CREATE TABLE IF NOT EXISTS `photo` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`url` varchar(255) DEFAULT NULL,
`thumb_url` varchar(255) DEFAULT NULL,
`user_id` int(11) NOT NULL,
`date` datetime NOT NULL,
`status` int(11) NOT NULL,
`votes` int(11) DEFAULT '0',
`comments` int(11) DEFAULT '0',
`views` int(11) DEFAULT '0',
`text` text,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `pm_conv` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` datetime NOT NULL,
`sender_id` int(11) NOT NULL,
`recipient_id` int(11) NOT NULL,
`last_answer_date` datetime NOT NULL,
`nb_messages` int(11) NOT NULL,
`is_read_sender` int(11) NOT NULL,
`is_read_recipient` int(11) NOT NULL DEFAULT '0',
`last_answer_user_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `recipient_id` (`recipient_id`),
KEY `sender_id` (`sender_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `pm_message` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` datetime NOT NULL,
`content` text NOT NULL,
`user_id` int(11) NOT NULL,
`conv_id` int(11) NOT NULL,
`read` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `conv_id` (`conv_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`encrypt_id` varchar(255) DEFAULT NULL,
`register_date` datetime DEFAULT NULL,
`last_login_date` datetime DEFAULT NULL,
`username` varchar(255) DEFAULT NULL,
`password` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`banned` int(11) DEFAULT NULL,
`banned_reason` text,
`first_step_form` int(11) DEFAULT '0',
`status` int(11) DEFAULT NULL,
`valid_snapchat` int(11) DEFAULT '0',
`introduced_forum` int(11) DEFAULT '0',
`referer` varchar(255) DEFAULT NULL,
`allow_social_featuring` int(11) DEFAULT NULL,
`rank` int(11) DEFAULT NULL,
`fb_id` bigint(20) DEFAULT NULL,
`rate_app_status` int(11) DEFAULT NULL,
`last_activity_date` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `user_info` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`gender` int(11) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`about` text,
`main_photo` int(11) DEFAULT NULL,
`country` varchar(100) DEFAULT NULL,
`city` varchar(100) DEFAULT NULL,
`relation_type` varchar(30) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`fb_link` varchar(255) DEFAULT NULL,
`twitter_link` varchar(255) DEFAULT NULL,
`youtube_link` varchar(255) DEFAULT NULL,
`instagram_link` varchar(255) DEFAULT NULL,
`app_pref_forum` int(11) DEFAULT NULL,
`app_pref_pm` int(11) DEFAULT NULL,
`app_pref_snapchat_request` int(11) DEFAULT NULL,
`browse_invisibly` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
KEY `main_photo` (`main_photo`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Can someone help me to optimize this heavy query?
Thanks!

you can see in the explain plan some tables are being accessed by inefficient indexes. try to calculate statistics on all the tables to see if it changes something (using analyze table).

You can join user table in order to get username and id at once instead of having two subqueries, probably you can do the same with pm_message, but it's a little trickier since subqueries have different conditions.
I would also combine user and user_info tables into, as I can see they have one-to-one relation, so it doesn't makes sense to store this data in different tables. This would allow you to get rid off 4th subquery and simplify the 5th one.
In some cases it is better to perform several queries instead of one with subqueries.

Related

select from two tables each with different join

Trying to run this query will not return any error but I guess there is still something wrong in it. After four minutes running it keeps elaborating:
SELECT DISTINCT azioni_row.id_az, sofferenze.Descrizione, COUNT(crediti.stato = 'aperta') as aperti, COUNT(crediti.stato = 'chiusa') as chiusi
FROM (`azioni_row`, sofferenze)
JOIN crediti ON azioni_row.id_cred=crediti.id_cre
JOIN azioni_head as ah1 ON azioni_row.id_az=ah1.id_az
JOIN azioni_head as ah2 ON ah2.id_soff = sofferenze.id_soff
GROUP BY id_az
ORDER BY `azioni_row`.`id_az` ASC
If I remove sofferenze.Descrizione from the select list and sofferenze from the FROM list it runs in a few seconds:
SELECT DISTINCT azioni_row.id_az, COUNT(crediti.stato = 'aperta') as aperti, COUNT(crediti.stato = 'chiusa') as chiusi
FROM azioni_row
JOIN crediti ON azioni_row.id_cred=crediti.id_cre
JOIN azioni_head as ah1 ON azioni_row.id_az=ah1.id_az
GROUP BY id_az
ORDER BY `azioni_row`.`id_az` ASC
I would like to show the Descrizione field but the link for it is in the head table, not in the row one. The relationship between head and row is a one to many. I store in head all the info that is not necessary to repeat for each row and the link with Descrizione is one of these fields.
EDIT:
this is the explain:
this is the create for azioni_head:
CREATE TABLE `azioni_head` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`tipo` varchar(2) NOT NULL,
`id_az` varchar(11) NOT NULL,
`id_soff` varchar(11) NOT NULL,
`id_soff_gar` varchar(11) DEFAULT NULL,
`date_from` date NOT NULL,
`date_to` date NOT NULL,
`close_why` int(11) NOT NULL,
`RGE` varchar(30) NOT NULL,
`procedente` varchar(2) NOT NULL,
`curatore` varchar(11) NOT NULL,
`legale` varchar(11) NOT NULL,
`tribunale` varchar(11) NOT NULL,
`riparto` varchar(2) NOT NULL DEFAULT '0',
`perc_worst` decimal(13,10) NOT NULL,
`perc_best` decimal(13,10) NOT NULL,
`perc_poster` decimal(13,10) NOT NULL,
`attivo_storico` decimal(65,2) NOT NULL,
`passivo_storico` decimal(65,2) NOT NULL,
`attivo_storico_comm` decimal(65,2) NOT NULL,
`passivo_storico_comm` decimal(65,2) NOT NULL,
`acconti` decimal(65,2) NOT NULL,
`acconti_comm` decimal(65,2) NOT NULL,
`numero_comm` int(11) NOT NULL,
`legali_worst` decimal(65,2) NOT NULL,
`legali_best` decimal(65,2) NOT NULL,
`manuale` tinyint(1) NOT NULL DEFAULT '0',
`created_by` int(11) NOT NULL,
`created_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1449 DEFAULT CHARSET=utf8 COMMENT='tabella testata azioni'
this for azioni_row:
CREATE TABLE `azioni_row` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_az` varchar(11) NOT NULL,
`id_cred` varchar(11) NOT NULL,
`chiesto` decimal(65,2) NOT NULL,
`ammesso` decimal(65,2) NOT NULL,
`data_ammesso` date NOT NULL,
`rango_ammesso` tinytext NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4479 DEFAULT CHARSET=utf8
and this for sofferenze
CREATE TABLE `sofferenze` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_soff` varchar(11) NOT NULL,
`Descrizione` tinytext NOT NULL,
`gruppo` int(11) NOT NULL,
`cointestazione` int(11) NOT NULL,
`port_man` tinytext NOT NULL,
`head_port_man` tinytext NOT NULL,
`note` longtext NOT NULL,
`created_on` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`created_by` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `id` (`id`),
UNIQUE KEY `id_3` (`id`),
KEY `id_2` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1716 DEFAULT CHARSET=utf8
Please provide proper CREATE statements as well as the output of:
EXPLAIN
SELECT a.id_az
, s.Descrizione
, COUNT(c.stato = 'aperta') aperti
, COUNT(c.stato = 'chiusa') chiusi
FROM azioni_row a
JOIN sofferenze s
CROSS
JOIN crediti c
ON c.id_cre = a.id_cred
JOIN azioni_head ah1
ON ah1.id_az = a.id_az
JOIN azioni_head ah2
ON ah2.id_soff = s.id_soff
GROUP
BY a.id_az
, s.Descrizione
ORDER
BY a.id_az ASC
Edit: You seem to have lots of indexes on the same column. Drop all indexes except the PRIMARY KEYs, and create the following indexes:
sofferenze: id_soff
azioni_row: try a composite index on (id_az,id_cred)
azioni_head: an index on id_soff and an index on id_az
Crediti is missing so I can't comment on that one.

sql can't figure out the query

I have three tables:
CREATE TABLE IF NOT EXISTS `contacts` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`providerId` int(10) unsigned NOT NULL DEFAULT '0',
`requestId` int(10) unsigned NOT NULL DEFAULT '0',
`status` binary(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
)
CREATE TABLE IF NOT EXISTS `messages` (
`id` int(255) NOT NULL AUTO_INCREMENT,
`fromuid` int(255) NOT NULL,
`touid` int(255) NOT NULL,
`sentdt` datetime NOT NULL,
`read` tinyint(1) NOT NULL DEFAULT '0',
`readdt` datetime DEFAULT NULL,
`messagetext` longtext CHARACTER SET utf8 COLLATE utf8_bin NOT NULL,
PRIMARY KEY (`id`),
KEY `id` (`id`)
)
CREATE TABLE IF NOT EXISTS `users` (
`id` bigint(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`email` varchar(255) DEFAULT NULL,
`mobile` varchar(15) NOT NULL,
`password` varchar(255) NOT NULL,
`city` varchar(255) NOT NULL,
`zip` varchar(15) DEFAULT NULL,
`device` varchar(50) DEFAULT NULL,
`version` varchar(10) DEFAULT NULL,
`photo` varchar(255) DEFAULT NULL,
`created` datetime NOT NULL,
`live` enum('0','1') NOT NULL DEFAULT '1',
`authenticationTime` datetime NOT NULL,
`userKey` varchar(255) DEFAULT NULL,
`IP` varchar(50) DEFAULT NULL,
`port` int(10) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `firstname` (`mobile`,`city`,`zip`)
)
And this SQL query that finds out friends/contacts for specified user (user id 1 in this case):
SELECT u.id
,u.mobile
,u.name
,(NOW() - u.authenticationTime) AS authenticateTimeDifference
,u.IP
,f.providerid
,f.requestid
,f.status
,u.port
FROM contacts f
LEFT JOIN users u ON u.id =
IF (
f.providerid = 1
,f.requestid
,f.providerid
) WHERE (
f.providerid = 1
AND f.status = 1
)
OR f.requestid = 1
That works fine but I want to be able to also join messages table and show user's friends/contacts who have talked latest (meaning latest conversations first) with order by messages.sentdt desc option but I am unable to figure out how to do that, I tried all joins but none worked :(
Your help will be greatly appreciated. Thanks
Update
Here is sample data above query returns:
In that same resultset, I want to be able to sort based on order by messages.sentdt desc but I am not sure how to pull that in and sort resultset by latest message first
Try this:
select u.id
, u.mobile
, u.name
, (NOW() - u.authenticationTime) as authenticateTimeDifference
, u.IP
, f.providerid
, f.requestid
, f.status
, u.port
from contacts f
left join users u
on u.id = if (f.providerid = 1, f.requestid, f.providerid)
left join (select fromuid, max(sentdt) as sentdt from messages group by fromuid) m
on m.fromuid = if (f.providerid = 1, f.providerid, f.requestid)
where (f.providerid = 1 and f.status = 1)
or f.requestid = 1
order by m.sentdt

Get number products on stock

I have very difficult query and I need obtain parameters (parameterValue_id) and number products, which has such parameter, on stock. I would like count only that products which are comply with other criterias.
SELECT `parameters`.`parameter_from`, `parametervalues`.*, (SELECT IF (sumOfProductIN - sumOfProductOUT > 0, COUNT(productparametervalues.f_product_id), 0) FROM productparametervalues`
LEFT JOIN `products` ON products.product_id = productparametervalues.f_product_id
LEFT JOIN `categories` ON categories.category_id = products.f_category_id
LEFT JOIN (SELECT oi1.f_product_id, SUM(oi1.orderItem_numberUnits) AS sumOfProductIN
FROM orderitems oi1 WHERE oi1.orderItem_type = 'IN' GROUP BY oi1.f_product_id) AS `t` ON t.f_product_id = products.product_id
LEFT JOIN (SELECT oi2.f_product_id, SUM(oi2.orderItem_numberUnits) AS sumOfProductOUT
FROM orderitems oi2 WHERE oi2.orderItem_type = 'OUT' GROUP BY oi2.f_product_id) AS `t_2` ON t_2.f_product_id = products.product_id
LEFT JOIN `parametervalues` ON parametervalues.f_parameter_id = parameters.parameter_id
WHERE (category_lft >= '8') AND (category_rgt <= '19') AND (products.product_price >= '1') AND (products.product_price <= '2500') AND (products.product_enabled = 1)
WHERE (parameter_id = '4') AND (parameters.parameter_enabled = 1) AND (parametervalues.parameterValue_enabled = 1)
GROUP BY `parametervalues`.`parameterValue_id`) AS countProducts FROM `parameters`
Edit
table categories
CREATE TABLE IF NOT EXISTS `categories` (
`category_id` int(11) NOT NULL AUTO_INCREMENT,
`category_title` varchar(255) DEFAULT NULL,
`category_description` text,
`f_parent_id` int(11) DEFAULT NULL,
`category_lft` smallint(6) DEFAULT NULL,
`category_rgt` smallint(6) DEFAULT NULL,
`category_depth` smallint(6) DEFAULT NULL,
`category_enabled` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`category_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=16 ;
table orderitems
CREATE TABLE IF NOT EXISTS `orderitems` (
`orderItem_id` int(11) NOT NULL AUTO_INCREMENT,
`f_order_id` int(11) DEFAULT NULL,
`f_product_id` int(11) DEFAULT NULL,
`orderItem_title` varchar(50) DEFAULT NULL,
`orderItem_numberUnits` smallint(6) NOT NULL DEFAULT '1',
`orderItem_pricePerUnit` decimal(18,5) NOT NULL DEFAULT '0.00000',
`orderItem_price` float(18,5) NOT NULL DEFAULT '0.00000',
`orderItem_type` varchar(10) DEFAULT NULL,
PRIMARY KEY (`orderItem_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=95 ;
table parameters
CREATE TABLE IF NOT EXISTS `parameters` (
`parameter_id` int(11) NOT NULL AUTO_INCREMENT,
`f_parameterGroup_id` int(11) DEFAULT NULL,
`parameter_title` varchar(100) DEFAULT NULL,
`parameter_enabled` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`parameter_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=10 ;
table parametervalues
CREATE TABLE IF NOT EXISTS `parametervalues` (
`parameterValue_id` int(11) NOT NULL AUTO_INCREMENT,
`f_parameter_id` int(11) NOT NULL,
`parameterValue_title` varchar(100) NOT NULL,
`parameterValue_enabled` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`parameterValue_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=20 ;
table productparametervalues
CREATE TABLE IF NOT EXISTS `productparametervalues` (
`f_product_id` int(11) NOT NULL AUTO_INCREMENT,
`f_parameter_id` int(11) NOT NULL DEFAULT '0',
`f_parameterValue_id` int(11) NOT NULL DEFAULT '0',
`productParameter_value` varchar(100) DEFAULT NULL,
PRIMARY KEY (`f_product_id`,`f_parameter_id`,`f_parameterValue_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=41 ;
table products
CREATE TABLE IF NOT EXISTS `products` (
`product_id` int(11) NOT NULL AUTO_INCREMENT,
`f_category_id` int(11) DEFAULT NULL,
`f_brand_id` int(11) DEFAULT NULL,
`product_title` varchar(100) DEFAULT NULL,
`product_description` text,
`product_price` float(10,2) DEFAULT NULL,
`product_enabled` tinyint(1) DEFAULT '0',
PRIMARY KEY (`product_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=43 ;

Updating table A.type = B.type WHERE A.id = B.id

I have two tables in different databases:
In the database named CRMALPHA:
CREATE TABLE IF NOT EXISTS `contacts` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`accountId` int(11) NOT NULL,
`Type` int(11) NOT NULL,
`fName` varchar(255) NOT NULL,
`lName` varchar(255) NOT NULL,
`title` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`workPhone` int(11) NOT NULL,
`workPhoneExt` int(11) NOT NULL,
`cellPhone` int(11) NOT NULL,
`altPhone` int(11) NOT NULL,
`altPhoneDescription` varchar(255) NOT NULL,
`dob` date NOT NULL,
`createdDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`createdById` int(11) NOT NULL,
`notes` varchar(255) NOT NULL,
`isDeleted` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
KEY `accountId` (`accountId`,`email`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=12006 ;
In the DB named scottse1_lifestyle_test
CREATE TABLE IF NOT EXISTS `tbl_customers_contact_types` (
`ContactId` int(4) NOT NULL DEFAULT '0',
`TypeId` int(5) NOT NULL DEFAULT '0',
PRIMARY KEY (`ContactId`,`TypeId`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
I need to:
UPDATE crmalpha.contacts
SET type = scottse1_lifestyle_test.tbl_customers_contact_types.TypeID
WHERE scottse1_lifestyle_test.tbl_customers_contact_types.ContactId = crmalpha.contacts.id
This causes the following error:
#1054 - Unknown column 'scottse1_lifestyle_test.tbl_customers_contact_types.ContactId' in 'where clause'
What am I doing wrong?
EDIT
Solution was:
UPDATE crmalpha.contacts c
JOIN scottse1_lifestyle_test.tbl_customers_contact_types t
ON t.ContactId = c.id
SET c.type = t.TypeId
You have to select the table in commaseperated way:
UPDATE CRMALPHA.contacts, scottse1_lifestyle_test.tbl_customers_contact_types
SET Type = scottse1_lifestyle_test.tbl_customers_contact_types.TypeID
WHERE scottse1_lifestyle_test.tbl_customers_contact_types.ContactId = CRMALPHA.contacts.id

MySQL - Slow Multiple subquery & GROUP BY

When running the following query using GROUP BY it takes way too much time.
SELECT specialities.id AS ID_DEPARTMENT,
specialities.name AS ID_DEPARTMENT_NAME,
agenda.idagenda AS ID_SERVICE,
agenda.name AS ID_SERVICE_NAME,
supervisor.clients_waiting AS CWaiting,
IFNULL(supervisor.clients_resent_waiting_area, 0) AS CWaiting_Resent_Area,
supervisor.clients_attending AS CAttending,
supervisor.clients_attended AS CAttended,
(SELECT SUM(TIME_TO_SEC(TIMEDIFF(NOW(), time_waiting)) / CWaiting)
FROM supervisor_time_data
WHERE supervisor_time_data.id_service = supervisor.id_service) AS TME,
(SELECT SUM(TIME_TO_SEC(TIMEDIFF(NOW(), time_attending)) / CAttending)
FROM supervisor_time_data
WHERE supervisor_time_data.id_service = supervisor.id_service) AS TMA,
(SELECT TIME_TO_SEC(MAX(TIMEDIFF(NOW(), time_waiting)))
FROM supervisor_time_data
WHERE supervisor_time_data.id_service = supervisor.id_service) AS MTE,
(SELECT TIME_TO_SEC(MAX(TIMEDIFF(NOW(), time_attending)))
FROM supervisor_time_data
WHERE supervisor_time_data.id_service = supervisor.id_service) AS MTA,
supervisor.tme_accumulated AS TME_ACCUMULATED,
supervisor.tma_accumulated AS TMA_ACCUMULATED
FROM supervisor, supervisor_time_data, agenda, specialities
WHERE supervisor.id_service = agenda.id
AND supervisor_time_data.id_service = supervisor.id_service
AND agenda.idspeciality = specialities.id
AND supervisor.booked_or_sequential = 0
AND supervisor.id_service IN (1,2,3)
GROUP BY supervisor.id_service
ORDER BY agenda.name ASC;
It takes over 3 seconds, when commenting the GROUP BY line it takes 8 ms.
Any ideas on how I can optimise this query?
Thanks
EDIT:
CREATE TABLE `supervisor` (
`id` int(9) NOT NULL AUTO_INCREMENT,
`id_department` int(6) DEFAULT NULL,
`id_service` int(9) DEFAULT NULL,
`clients_waiting` int(6) DEFAULT '0',
`clients_attending` int(6) DEFAULT '0',
`clients_attended` int(6) DEFAULT '0',
`tma_accumulated` int(9) DEFAULT '0',
`tme_accumulated` int(9) DEFAULT '0',
`clients_resent_waiting_area` int(6) DEFAULT NULL,
`booked_or_sequential` tinyint(1) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id_service` (`id_service`),
KEY `booked_or_sequential` (`booked_or_sequential`),
KEY `clients_waiting` (`clients_waiting`)
) ENGINE=MyISAM AUTO_INCREMENT=172 DEFAULT CHARSET=latin1;
.
CREATE TABLE `supervisor_time_data` (
`id` int(9) NOT NULL AUTO_INCREMENT,
`id_ogs` int(32) DEFAULT NULL,
`booked_or_sequential` tinyint(1) DEFAULT NULL,
`time_waiting` datetime DEFAULT NULL,
`time_attending` datetime DEFAULT NULL,
`status` int(2) DEFAULT '0',
`id_service` int(6) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `id_service` (`id_service`),
KEY `time_waiting` (`time_waiting`),
KEY `time_attending` (`time_attending`),
KEY `booked_or_sequential` (`booked_or_sequential`)
) ENGINE=MyISAM AUTO_INCREMENT=2281 DEFAULT CHARSET=latin1;
.
CREATE TABLE `agenda` (
`id` int(3) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`idagenda` varchar(255) DEFAULT NULL,
`iduser` int(3) DEFAULT NULL,
`date_created` datetime DEFAULT NULL,
`agendatype` tinyint(4) DEFAULT NULL,
`idspeciality` int(6) DEFAULT NULL,
`denomination` varchar(255) DEFAULT NULL,
`ticket_count` int(3) DEFAULT NULL,
`waiting` int(3) DEFAULT NULL,
`ticket_start` int(3) DEFAULT NULL,
`ticket_end` int(3) DEFAULT NULL,
`ticket_letter` varchar(12) DEFAULT NULL,
`idcenter` int(9) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `idagenda` (`idagenda`),
KEY `idspeciality` (`idspeciality`)
) ENGINE=MyISAM AUTO_INCREMENT=2228 DEFAULT CHARSET=latin1;
.
CREATE TABLE `specialities` (
`id` int(6) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`date_created` datetime DEFAULT NULL,
`idwaitingarea` int(3) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=149 DEFAULT CHARSET=latin1;
Here is your queries with joins. Post your schema if this does not work.
SELECT
specialities.id AS ID_DEPARTMENT,
specialities.name AS ID_DEPARTMENT_NAME,
agenda.idagenda AS ID_SERVICE,
agenda.name AS ID_SERVICE_NAME,
supervisor.clients_waiting AS CWaiting,
IFNULL(supervisor.clients_resent_waiting_area, 0) AS CWaiting_Resent_Area,
supervisor.clients_attending AS CAttending,
supervisor.clients_attended AS CAttended,
SUM(TIME_TO_SEC(TIMEDIFF(NOW(), supervisor_time_data.time_waiting)) / supervisor.clients_waiting) AS TME,
SUM(TIME_TO_SEC(TIMEDIFF(NOW(), supervisor_time_data.time_attending)) / supervisor.clients_attending) AS TMA,
TIME_TO_SEC(MAX(TIMEDIFF(NOW(), supervisor_time_data.time_waiting))) AS MTE,
TIME_TO_SEC(MAX(TIMEDIFF(NOW(), supervisor_time_data.time_attending))) AS MTA,
supervisor.tme_accumulated AS TME_ACCUMULATED,
supervisor.tma_accumulated AS TMA_ACCUMULATED
FROM supervisor
LEFT JOIN supervisor_time_data
ON supervisor_time_data.id_service = supervisor.id_service
LEFT JOIN agenda
ON supervisor.id_service = agenda.id
LEFT JOIN specialities
ON agenda.idspeciality = specialities.id
WHERE supervisor.booked_or_sequential = 0
AND supervisor.id_service IN(1,2,3)
GROUP BY supervisor.id_service
ORDER BY agenda.name ASC;