MySQL query is extremely slow - mysql

I have a complex SQL query that linked 6 tables and I found out that it takes about 2 minutes (which I think it shouldn't) to display the result. The result will return about 5400++ records. Is there any way to redesign the query so that it will be able to execute a bit faster? Thank you for help!
My current query is:
SELECT *,
(SELECT MasterDescription FROM sys_master_code WHERE MasterId = mktg_account.CategoryId) AS CustomerCategory,
(CASE WHEN mktg_account.BusinessSourceId = 97 THEN mktg_account.BusinessSourceOthers ELSE (SELECT MasterDescription FROM sys_master_code WHERE MasterId = mktg_account.BusinessSourceId) END) AS BusinessSource,
(SELECT TreeName FROM sys_tree WHERE TreeId = mktg_account.TreeId) AS PhaseName,
(SELECT SolicitorName FROM sys_solicitor WHERE sys_solicitor.SolicitorId =(SELECT SolicitorId FROM mktg_spa WHERE mktg_spa.AccountId = mktg_account.AccountId)) AS SolicitorName,
(SELECT MasterCode FROM sys_master_code WHERE sys_master_code.MasterId = mktg_account.AgentCompany) AS AgentCompanyText,
(SELECT MasterCode FROM sys_master_code WHERE sys_master_code.MasterId = mktg_account.FinancialTypeId) AS FinanceSource,
(SELECT UserName FROM sys_user WHERE UserId = mktg_account.CreatedBy) AS CreatedByName
FROM mktg_account
WHERE TreeId IN (SELECT TreeId FROM sys_user_access_right WHERE UserId = 4)
AND IsApproved = '1' AND IsDeleted <>'1'
ORDER BY AccountNo
CREATE TABLE IF NOT EXISTS mktg_account (
AccountId int(10) unsigned NOT NULL AUTO_INCREMENT,
AccountNo varchar(30) NOT NULL DEFAULT '',
AccountStatus varchar(1) DEFAULT NULL,
TreeId int(10) unsigned NOT NULL DEFAULT '0',
SalesDate datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
PurchasePrice double NOT NULL DEFAULT '0',
SalesPersonId int(10) unsigned DEFAULT NULL,
FinancialTypeId int(10) unsigned DEFAULT NULL,
BillingCustomerId int(10) unsigned DEFAULT NULL,
EventId int(11) NOT NULL DEFAULT '0',
CategoryId int(11) NOT NULL DEFAULT '0',
RealEstateAgentId int(11) NOT NULL DEFAULT '0',
BusinessSourceId int(10) unsigned DEFAULT NULL,
BusinessSourceOthers varchar(300) DEFAULT NULL,
SalesPromotionId int(10) unsigned DEFAULT NULL,
Remarks text,
AgentName varchar(100) NOT NULL DEFAULT '',
AgentCompany varchar(100) NOT NULL DEFAULT '',
AgentContact varchar(100) DEFAULT NULL,
AgentRemarks text,
CreatedDateTime datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
CreatedBy int(10) unsigned NOT NULL DEFAULT '0',
PurgedDateTime datetime DEFAULT NULL,
PurgedBy int(10) unsigned DEFAULT NULL,
PurgedIP varchar(20) DEFAULT NULL,
IsDeleted tinyint(3) unsigned NOT NULL DEFAULT '0',
IsApproved tinyint(3) unsigned NOT NULL DEFAULT '1',
IsPurge tinyint(3) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (AccountId)
)
CREATE TABLE IF NOT EXISTS sys_master_code (
MasterId int(10) unsigned NOT NULL AUTO_INCREMENT,
MasterType varchar(20) NOT NULL DEFAULT '',
MasterCode varchar(100) NOT NULL DEFAULT '',
MasterDescription varchar(500) NOT NULL DEFAULT '',
CreatedDateTime datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
CreatedBy int(10) unsigned NOT NULL DEFAULT '0',
CreatedIP varchar(20) NOT NULL DEFAULT '',
IsDeleted tinyint(3) unsigned NOT NULL DEFAULT '0',
IsApproved tinyint(3) unsigned NOT NULL DEFAULT '1',
IsActive varchar(1) NOT NULL DEFAULT 'Y',
PRIMARY KEY (MasterId)
)
CREATE TABLE IF NOT EXISTS sys_tree (
TreeId int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Tree Running Id',
TreeName varchar(150) NOT NULL DEFAULT '',
IsDeleted tinyint(3) unsigned DEFAULT NULL COMMENT '1 = deleted',
PRIMARY KEY (TreeId)
)
CREATE TABLE IF NOT EXISTS sys_solicitor (
SolicitorId int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'Running id number',
SolicitorCode varchar(50) NOT NULL DEFAULT '',
SolicitorName varchar(150) NOT NULL DEFAULT '',
SolicitorType varchar(50) NOT NULL DEFAULT '',
ContactPerson varchar(50) NOT NULL DEFAULT '',
PhoneNo varchar(50) NOT NULL DEFAULT '' COMMENT 'phone number',
Email varchar(40) NOT NULL DEFAULT '' COMMENT 'email address',
CreatedDateTime datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
CreatedBy int(10) unsigned NOT NULL DEFAULT '0',
IsDeleted tinyint(3) unsigned DEFAULT NULL COMMENT '1 = deleted',
IsApproved tinyint(3) unsigned DEFAULT NULL COMMENT '0 = waiting approval',
PRIMARY KEY (SolicitorId)
)
CREATE TABLE IF NOT EXISTS sys_user (
UserId int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT 'User Running Id',
UserLoginId varchar(25) NOT NULL DEFAULT '' COMMENT 'User Name For Log In',
UserName varchar(150) NOT NULL DEFAULT '' COMMENT 'User Real Name',
Password varchar(50) NOT NULL DEFAULT '' COMMENT 'Password For Log in',
EmailAddress varchar(100) NOT NULL DEFAULT '',
IsDeleted tinyint(3) unsigned DEFAULT NULL COMMENT '1 = deleted',
CreatedDateTime datetime NOT NULL DEFAULT '0000-00-00 00:00:00' COMMENT 'Date and time this record created',
CreatedBy int(10) unsigned NOT NULL DEFAULT '0',
IsApproved tinyint(3) unsigned DEFAULT NULL COMMENT '0 = waiting approval',
IsActive varchar(1) NOT NULL DEFAULT 'Y',
PRIMARY KEY (UserId)
)
CREATE TABLE IF NOT EXISTS sys_user_access_right (
UserId int(10) unsigned NOT NULL AUTO_INCREMENT,
TreeId int(10) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (UserId,TreeId),
KEY FK_SysUserAccessRight_SysTree (TreeId)
)
CREATE TABLE IF NOT EXISTS mktg_spa (
SpaId int(10) unsigned NOT NULL AUTO_INCREMENT,
AccountId int(10) unsigned NOT NULL DEFAULT '0',
SPADate datetime DEFAULT NULL,
AgreementNo varchar(50) DEFAULT NULL,
AgreementStatus varchar(10) DEFAULT NULL,
AgreementDate datetime DEFAULT NULL,
SPAReference varchar(100) DEFAULT NULL,
SolicitorId int(10) unsigned DEFAULT NULL,
SolicitorRefNo varchar(50) DEFAULT NULL,
TitleDetailReason varchar(200) DEFAULT NULL,
Remark text,
CreatedDateTime datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
CreatedBy int(10) unsigned NOT NULL DEFAULT '0',
IsDeleted tinyint(3) unsigned NOT NULL DEFAULT '0',
IsApproved tinyint(3) unsigned NOT NULL DEFAULT '1',
PRIMARY KEY (SpaId)
)
I run EXPLAIN and it show the table :Query Analysis

You should use join instead of subqueries. Written with join, your query would look like
SELECT mktg_account.*,
tbCustomerCategory.MasterDescription as CustomerCategory,
(CASE WHEN mktg_account.BusinessSourceId = 97
THEN mktg_account.BusinessSourceOthers
ELSE tbBusinessSource.MasterDescription
END) AS BusinessSource,
sys_tree.TreeName as PhaseName,
sys_solicitor.SolicitorName,
tbAgentCompanyText.MasterCode as AgentCompanyText,
tbFinanceSource.MasterCode as FinanceSource,
sys_user.UserName as CreatedByName
from mktg_account
left join sys_master_code as tbCustomerCategory on tbCustomerCategory.MasterId = mktg_account.CategoryId
left join sys_master_code as tbBusinessSource on tbBusinessSource.MasterId = mktg_account.BusinessSourceId
left join sys_tree on sys_tree.TreeId = mktg_account.TreeId
left join mktg_spa on mktg_spa.AccountId = mktg_account.AccountId
left join sys_solicitor on sys_solicitor.SolicitorId = mktg_spa.SolicitorId
left join sys_master_code as tbAgentCompanyText on tbAgentCompanyText.MasterId = mktg_account.AgentCompany
left join sys_master_code as tbFinanceSource on tbFinanceSource.MasterId = mktg_account.FinancialTypeId
left join sys_user on sys_user.UserId = mktg_account.CreatedBy
join sys_user_access_right on sys_user_access_right.TreeId = mktg_account.TreeId
WHERE sys_user_access_right.UserId = 4
AND mktg_account.IsApproved = '1' AND mktg_account.IsDeleted <> '1'
ORDER BY mktg_account.AccountNo;
And you are missing an index on mktg_spa, so add it:
create index idx_mktg_spa_AccountId on mktg_spa (AccountId);
(You might want to try this first, it might already improve your query enough without converting it to join).
There might be some potential for an index on mktg_account, but it really depends on your data. If most of your rows are "deleted" or "not approved", you can try e.g.
create index idx_mktg_account_IsApprovedAccountNoIsDeleted
on mktg_account (IsApproved, AccountNo, IsDeleted);
But if your query returns more than just a small percentage of your rows, this index might actually slow down your query, so test without it first.

I'm not going to rewrite the whole thing for you, but here's a start. Appropriately indexed, this solution will be orders of magnitude faster than what you currently have...
SELECT a.*
, c.MasterDescription CustomerCategory
FROM mktg_account a
JOIN sys_master_code c
ON c.MasterId = a.CategoryId
JOIN sys_user_access_right r
ON r.TreeId = a.TreeId
WHERE r.UserId = 4
AND a.IsApproved = 1
AND IsDeleted <> 1
ORDER
BY a.AccountNo

Related

MySQL UNION query is taking time

In below query there are three UNIONs. each union is taking 4 seconds to execute and total query execution time is 12 seconds. is there any way to fine tune or re write this query? Each union has different columns in where clause, so adding more index also not good choice.
Select distinct el.ProblemID,el.SLAID,et.Esca_level from escalation_lookup el, sd_servicereqmaster s,escalation_timeslots et, escalation_details ed where s.ProblemID = el.ProblemID and el.IsEsca1_Breached = 0 and el.SLAID = et.SLA_ID and et.Esca_level = 1 and ed.SLA_ID = et.SLA_ID and ed.SLA_ID = el.SLAID and ed.IsSLARuleActive = 1 and Estimated_Esca1_BreachTime <> '0000-00-00 00:00:00' and Interval_time=1 and NBD_cutoff_time=0
and ((el.TotalTimeConsider > et.EscaTime_Min and el.IsTicketActive = 0) OR (el.TotalTimeConsider > et.EscaTime_Min and el.Previous_Status = 0 and el.IsTicketActive = 1) OR (el.Previous_Status = 1 and el.IsTicketActive = 1 and Estimated_Esca1_BreachTime < now()))
union all
Select distinct el.ProblemID,el.SLAID,et.Esca_level from escalation_lookup el, sd_servicereqmaster s,escalation_timeslots et, escalation_details ed where s.ProblemID = el.ProblemID and el.IsEsca2_Breached = 0 and el.SLAID = et.SLA_ID and et.Esca_level = 2 and ed.SLA_ID = et.SLA_ID and ed.SLA_ID = el.SLAID and ed.IsSLARuleActive = 1 and Estimated_Esca2_BreachTime <> '0000-00-00 00:00:00' and Interval_time=1 and NBD_cutoff_time=0
and ((el.TotalTimeConsider > et.EscaTime_Min and el.IsTicketActive = 0) OR (el.TotalTimeConsider > et.EscaTime_Min and el.Previous_Status = 0 and el.IsTicketActive = 1) OR (el.Previous_Status = 1 and el.IsTicketActive = 1 and Estimated_Esca2_BreachTime < now()))
union all
Select distinct el.ProblemID,el.SLAID,et.Esca_level from escalation_lookup el, sd_servicereqmaster s,escalation_timeslots et, escalation_details ed where s.ProblemID = el.ProblemID and el.IsEsca3_Breached = 0 and el.SLAID = et.SLA_ID and et.Esca_level = 3 and ed.SLA_ID = et.SLA_ID and ed.SLA_ID = el.SLAID and ed.IsSLARuleActive = 1 and Estimated_Esca3_BreachTime <> '0000-00-00 00:00:00' and Interval_time=1 and NBD_cutoff_time=0
and ((el.TotalTimeConsider > et.EscaTime_Min and el.IsTicketActive = 0) OR (el.TotalTimeConsider > et.EscaTime_Min and el.Previous_Status = 0 and el.IsTicketActive = 1) OR (el.Previous_Status = 1 and el.IsTicketActive = 1 and Estimated_Esca3_BreachTime < now()))
different column used in each union are
UNION 1
IsEsca1_Breached
Esca_level =1
Estimated_Esca1_BreachTime
UNION 2
IsEsca2_Breached
Esca_level =2
Estimated_Esca2_BreachTime
UNION 3
IsEsca3_Breached
Esca_level =3
Estimated_Esca3_BreachTime
table1,
CREATE TABLE escalation_lookup (
SiteID int(11) NOT NULL DEFAULT '1',
slno int(10) unsigned NOT NULL AUTO_INCREMENT,
SlaID int(11) unsigned NOT NULL DEFAULT '0',
ProblemID int(11) unsigned NOT NULL DEFAULT '0',
Esca_1 int(10) unsigned NOT NULL DEFAULT '0',
Esca_2 int(10) unsigned NOT NULL DEFAULT '0',
EmailEsca_1 int(11) NOT NULL DEFAULT '0',
EmailEsca_2 int(11) NOT NULL DEFAULT '0',
SLA_BreachTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
Esca1_BreachTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
Esca1_SendTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
Esca2_BreachTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
Esca2_SendTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
LastCalculatedTime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
Previous_Status tinyint(4) DEFAULT '1',
TotalTimeConsider int(11) DEFAULT '0',
IsTicketActive tinyint(4) DEFAULT '1',
TicketGenStatus varchar(8) DEFAULT '00',
Estimated_SLABreachTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
Estimated_Esca1_BreachTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
Estimated_Esca2_BreachTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
Estimated_GracePeriod_BreachTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
IsSLA_Breached tinyint(4) DEFAULT '0',
IsEsca1_Breached tinyint(4) DEFAULT '0',
IsEsca2_Breached tinyint(4) DEFAULT '0',
IsActualResolutionTimeConsider tinyint(4) DEFAULT '0',
Esca_3 int(10) unsigned NOT NULL DEFAULT '0',
EmailEsca_3 int(10) unsigned NOT NULL DEFAULT '0',
Esca3_BreachTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
Esca3_SendTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
Estimated_Esca3_BreachTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
IsEsca3_Breached tinyint(4) NOT NULL DEFAULT '0',
PRIMARY KEY (slno),
KEY Problem_ID (ProblemID),
KEY SLAStatus_ProblemID (ProblemID,IsSLA_Breached),
KEY Combined_key (ProblemID,IsEsca1_Breached,IsEsca2_Breached,SlaID),
KEY Estimated_SLABreachTime (Estimated_SLABreachTime),
KEY probleimid_slaid (ProblemID,SlaID),
KEY TotalTimeConsider (TotalTimeConsider),
KEY slaid (SlaID),
KEY slaid_problemid (SlaID,ProblemID)
) ENGINE=InnoDB AUTO_INCREMENT=7755116 DEFAULt utf8.
table 2
CREATE TABLE sd_servicereqmaster (
ProblemId int(11) NOT NULL AUTO_INCREMENT,
Title varchar(2048) CHARACTER SET utf8 NOT NULL DEFAULT '',
SubmittedBy int(11) NOT NULL,
Owner int(11) NOT NULL DEFAULT '0',
CurrentStatus int(11) NOT NULL,
Category int(11) NOT NULL,
SubCategory int(11) NOT NULL,
Platform int(11) NOT NULL DEFAULT '0',
Severity int(11) NOT NULL DEFAULT '0',
CreationTime timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
ProbDescription mediumtext CHARACTER SET utf8 NOT NULL,
CcMailId text CHARACTER SET utf8,
AlternativeEmail varchar(128) CHARACTER SET utf8 DEFAULT '',
ContactNumber varchar(256) CHARACTER SET utf8 DEFAULT '',
Attachment varchar(512) CHARACTER SET utf8 NOT NULL DEFAULT '',
Enclosure varchar(200) CHARACTER SET utf8 NOT NULL DEFAULT '',
Priority int(11) NOT NULL DEFAULT '0',
ApprovalManager int(10) unsigned NOT NULL DEFAULT '0',
LocationID int(10) unsigned NOT NULL DEFAULT '1',
DepartmentID int(10) unsigned NOT NULL DEFAULT '1',
Resolution_CauseID int(10) unsigned NOT NULL DEFAULT '0',
Resolution_Days varchar(45) CHARACTER SET utf8 NOT NULL DEFAULT '0',
Resolution_Hours varchar(45) CHARACTER SET utf8 NOT NULL DEFAULT '0',
Resolution_Minutes varchar(45) CHARACTER SET utf8 NOT NULL DEFAULT '0',
SubmittedThrough int(10) unsigned NOT NULL DEFAULT '0',
AlertID int(11) NOT NULL DEFAULT '0',
LastOperatedTime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
GroupID int(11) NOT NULL DEFAULT '0',
RepeatCall int(11) NOT NULL DEFAULT '0',
ResolutionComment text CHARACTER SET utf8,
REQUESTTYPE int(10) unsigned NOT NULL DEFAULT '1',
AssetNumber int(10) unsigned NOT NULL DEFAULT '0',
SLAViolationComment varchar(1024) CHARACTER SET utf8 NOT NULL DEFAULT '',
ParentID int(11) NOT NULL DEFAULT '0',
ConversionType tinyint(3) unsigned NOT NULL DEFAULT '0',
DerivedField1 int(10) unsigned NOT NULL DEFAULT '0',
DerivedField2 int(10) unsigned NOT NULL DEFAULT '0',
DerivedField3 int(10) unsigned NOT NULL DEFAULT '0',
RequestID varchar(3000) CHARACTER SET utf8 NOT NULL DEFAULT ' ',
ProjectID int(10) unsigned NOT NULL DEFAULT '1',
ServiceID int(10) unsigned NOT NULL DEFAULT '1',
IsTransferred int(10) unsigned NOT NULL DEFAULT '0',
ReferenceID varchar(1024) CHARACTER SET utf8 NOT NULL DEFAULT '',
LevelOneStatus tinyint(4) NOT NULL DEFAULT '0',
LevelTwoStatus tinyint(4) NOT NULL DEFAULT '0',
ProxySubmittedBy int(10) unsigned NOT NULL DEFAULT '0',
DelegatedFrom_Owner int(10) unsigned NOT NULL DEFAULT '0',
DelegatedFrom_ApprovalManager int(10) unsigned NOT NULL DEFAULT '0',
UrgencyID int(10) unsigned NOT NULL DEFAULT '0',
ImpactID int(10) unsigned NOT NULL DEFAULT '0',
isLinked int(10) unsigned NOT NULL DEFAULT '0',
CSI int(10) unsigned NOT NULL DEFAULT '0',
IncidentType int(10) unsigned NOT NULL DEFAULT '0',
ExpectedClosureTime varchar(45) CHARACTER SET utf8 NOT NULL DEFAULT '',
ProjectTransferComment text CHARACTER SET utf8,
IsRead tinyint(3) unsigned NOT NULL DEFAULT '0',
IsRead_UserID int(10) unsigned NOT NULL DEFAULT '0',
SchedulerecordType int(10) NOT NULL DEFAULT '0',
VERSION int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (ProblemId),
KEY Owner_SubmittedBy (SubmittedBy,Owner),
KEY Current_Status (CurrentStatus),
KEY Sub_Category (SubCategory),
KEY Creation_Time (CreationTime),
KEY FK_sd_servicereqmaster_1 (ProjectID),
KEY FK_sd_servicereqmaster_2 (ServiceID),
KEY FK_sd_servicereqmaster_3 (Category),
KEY index_LocationID (LocationID),
KEY index_DepartmentID (DepartmentID),
KEY index_ImpactID (ImpactID),
KEY index_UrgencyID (UrgencyID),
KEY index_Priority (Priority),
KEY index_GroupID (GroupID),
KEY index_SubmittedThrough (SubmittedThrough),
KEY index_ApprovalManager (ApprovalManager),
KEY index_DerivedField1 (DerivedField1),
KEY index_DerivedField2 (DerivedField2),
KEY index_DerivedField3 (DerivedField3),
KEY index_RequestID (RequestID(255)),
KEY ParentID (ParentID),
KEY owner (Owner),
KEY isLinked (isLinked),
CONSTRAINT FK_sd_servicereqmaster_1 FOREIGN KEY (ProjectID) REFERENCES sd_project_master (ProjectID) ON DELETE CASCADE,
CONSTRAINT FK_sd_servicereqmaster_2 FOREIGN KEY (ServiceID) REFERENCES sd_service (ServiceID) ON DELETE CASCADE
);
table 3
CREATE TABLE escalation_details (
SiteID int(11) NOT NULL DEFAULT '1',
SLA_ID int(11) NOT NULL AUTO_INCREMENT,
Name varchar(256) DEFAULT '',
Formula varchar(255) DEFAULT '',
Rule varchar(4096) DEFAULT '',
ResolveTime varchar(255) DEFAULT '',
ResolveTime_Min int(11) DEFAULT '0',
GraceTime varchar(255) DEFAULT '0 Day(s) 0 Hour(s) 0 Mins',
GraceTime_Min int(11) DEFAULT '0',
Description varchar(255) DEFAULT '',
TicketGenID int(10) DEFAULT '0',
IsSLARuleActive int(11) DEFAULT '1',
BusinessHrs_Profile int(11) DEFAULT '0',
Holidays_Profile int(11) DEFAULT '0',
ProjectID int(10) unsigned NOT NULL DEFAULT '1',
IsResponseRequired int(10) NOT NULL DEFAULT '1' COMMENT '1-Enable Alert Message, 0-Disable Alert Message',
Interval_time int(10) NOT NULL DEFAULT '1',
NBD_cutoff_time int(10) NOT NULL DEFAULT '0',
NBD_without_cutofftime_Businessday int(10) NOT NULL DEFAULT '0',
NBD_With_Cutofftime time NOT NULL DEFAULT '00:00:00',
NBD_With_before_cutofftime_Businessday int(10) NOT NULL DEFAULT '0',
NBD_With_After_cutofftime_Businessday int(10) NOT NULL DEFAULT '0',
Additionalfieldid int(10) NOT NULL DEFAULT '0',
PRIMARY KEY (SLA_ID),
KEY FK_escalation_details_1 (ProjectID),
KEY NBD_cutoff_time (NBD_cutoff_time),
KEY sla_id (SLA_ID),
CONSTRAINT FK_escalation_details_1 FOREIGN KEY (ProjectID) REFERENCES sd_project_master (ProjectID) ON DELETE CASCADE
) ;

Select items from 3 different tables

I would like to select items from 3 different tables, I am using UNION, but the number of columns is different, so it returns an error of number of columns, is there any other way using JOIN to get an appreciated result?
SELECT *
FROM `ads` JOIN ad_car
ON ads.id_ads = ad_car.main_ad
WHERE ads_cat = :ads_cat AND
ads.ad_status = :adStatus
UNION
SELECT *
FROM `ads` JOIN ad_vehpro
ON ads.id_ads = ad_vehpro.main_ad
WHERE ads_cat = :ads_cat AND
ads.ad_status = :adStatus
ORDER BY date_renewed
DESC LIMIT 4
EDITED: I add the tables:
CREATE TABLE IF NOT EXISTS `ads` (
`id_ads` int(10) unsigned NOT NULL AUTO_INCREMENT,
`id_profiles_key` varchar(20) NOT NULL,
`id_shops` int(4) NOT NULL DEFAULT '1',
`ads_cat` int(2) NOT NULL COMMENT 'main category: vehicule, immobilier,...',
`ads_scat` int(3) NOT NULL COMMENT 'sous cat: voiture, moto,...',
`form_id` varchar(30) NOT NULL COMMENT 'form key',
`city_id` int(5) NOT NULL,
`district_id` int(5) NOT NULL,
`adtype_id` int(1) NOT NULL DEFAULT '1' COMMENT '1: offre, 2: demande',
`ads_title` varchar(200) NOT NULL,
`ads_description` longtext NOT NULL,
`ads_price` int(11) NOT NULL,
`num_img` int(2) NOT NULL DEFAULT '1' COMMENT 'number of images',
`num_vid` int(2) NOT NULL DEFAULT '0' COMMENT 'number of video',
`num_com` int(3) NOT NULL DEFAULT '0' COMMENT 'number of comments',
`to_pin` int(1) NOT NULL DEFAULT '0' COMMENT 'ad that will be pinned. 0: no, 1: yes',
`date_inserted` varchar(20) NOT NULL,
`date_modified` varchar(20) NOT NULL,
`date_renewed` varchar(20) NOT NULL,
`date_pinned` varchar(20) NOT NULL DEFAULT '0',
`ad_status` int(1) NOT NULL DEFAULT '1' COMMENT '0: not active, 1: active, 2: deleted, 3: pinned',
PRIMARY KEY (`id_ads`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;
CREATE TABLE IF NOT EXISTS `ad_car` (
`id_ad` int(10) unsigned NOT NULL AUTO_INCREMENT,
`main_ad` int(5) NOT NULL COMMENT 'this will refer to main table ads (id_ads)',
`id_profiles` varchar(20) NOT NULL,
`city_id` int(5) NOT NULL,
`district_id` int(5) NOT NULL COMMENT 'district id from districts table',
`category_id` int(2) NOT NULL,
`make_id` int(5) NOT NULL,
`model_id` int(5) NOT NULL,
`model_year` int(4) NOT NULL,
`engine` int(2) NOT NULL,
`fuel` int(1) NOT NULL,
`mileage` bigint(7) NOT NULL,
`transmission` int(1) NOT NULL,
`wheed_drive` int(1) NOT NULL,
`in_color` varchar(7) NOT NULL,
`ex_color` varchar(7) NOT NULL,
`seats` int(2) NOT NULL,
`doors` int(1) NOT NULL,
`tax` varchar(5) NOT NULL,
`warranty` int(1) NOT NULL,
`hands` int(1) NOT NULL,
`security` longtext NOT NULL,
`comfort` longtext NOT NULL,
`aesthetic` longtext NOT NULL,
`adreference` varchar(10) NOT NULL,
`ad_price` bigint(20) NOT NULL,
`ad_priceneg` int(1) NOT NULL,
`when_inserted` varchar(20) NOT NULL,
`when_modified` varchar(20) NOT NULL,
`ad_status` int(1) NOT NULL DEFAULT '1' COMMENT '0: not active, 1: active, 2: deleted',
`not_listed` longtext NOT NULL,
PRIMARY KEY (`id_ad`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=6 ;
CREATE TABLE IF NOT EXISTS `ad_vehpro` (
`id_ad` int(10) unsigned NOT NULL AUTO_INCREMENT,
`main_ad` int(5) NOT NULL COMMENT 'this will refer to main table ads (id_ads)',
`id_profiles` varchar(20) NOT NULL,
`city_id` int(5) NOT NULL,
`district_id` int(5) NOT NULL COMMENT 'district id from districts table',
`category_id` int(2) NOT NULL,
`vehpro_type` int(1) NOT NULL,
`make_id` int(5) NOT NULL,
`model_id` int(5) NOT NULL,
`model_year` int(4) NOT NULL,
`engine` int(2) NOT NULL,
`fuel` int(1) NOT NULL,
`mileage` bigint(7) NOT NULL,
`transmission` int(1) NOT NULL,
`wheed_drive` int(1) NOT NULL,
`in_color` varchar(7) NOT NULL,
`ex_color` varchar(7) NOT NULL,
`seats` int(2) NOT NULL,
`doors` int(1) NOT NULL,
`tax` varchar(5) NOT NULL,
`warranty` int(1) NOT NULL,
`hands` int(1) NOT NULL,
`security` longtext NOT NULL,
`comfort` longtext NOT NULL,
`aesthetic` longtext NOT NULL,
`adreference` varchar(10) NOT NULL,
`ad_price` bigint(20) NOT NULL,
`ad_priceneg` int(1) NOT NULL,
`when_inserted` varchar(20) NOT NULL,
`when_modified` varchar(20) NOT NULL,
`ad_status` int(1) NOT NULL DEFAULT '1' COMMENT '0: not active, 1: active, 2: deleted',
`not_listed` longtext NOT NULL,
PRIMARY KEY (`id_ad`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
EDITED
I tried using LEFT JOIN but, it skips some fields:
$sqlAds = "SELECT * FROM `ads`"
. " LEFT JOIN ad_car ON ads.id_ads = ad_car.main_ad"
. " LEFT JOIN ad_vehpro ON ads.id_ads = ad_vehpro.main_ad"
. " WHERE ads_cat = :ads_cat AND ads.ad_status = :adStatus ORDER BY date_renewed DESC";
Thanks in advance
List the columns you explicitly want. Provide NULLvalues for the rest:
SELECT a.*, c.col1, c.col2
FROM `ads` a JOIN
ad_car c
ON a.id_ads = c.main_ad
WHERE ads_cat = :ads_cat AND
a.ad_status = :adStatus
UNION
SELECT a.*, v.col1, NULL as col2
FROM ads a JOIN
ad_vehpro v
ON a.id_ads = v.main_ad
WHERE ads_cat = :ads_cat AND
a.ad_status = :adStatus
ORDER BY date_renewed DESC
LIMIT 4;
Note: If you know there are no duplicates between the two subqueries, use UNION ALL rather than UNION. UNION incurs the overhead of removing duplicates.

Sorting users by country code

Ive got a query here, i'd like it to list the countries by the most country count. However, its giving me an error, if anyone can help it would be much appreciated!
Here is the query!
SELECT country_code,count(country_code) FROM `users`
GROUP BY country_code
ORDER BY `users`.`id`
DESC LIMIT 50;
So it'd be like
| US | 150 |
| CA | 200 |
Table Structure
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(50) NOT NULL,
`real_name` varchar(50) NOT NULL,
`mail` varchar(50) NOT NULL DEFAULT 'defaultuser#other.org',
`rank` int(11) unsigned NOT NULL DEFAULT '1',
`motto` varchar(255) NOT NULL DEFAULT 'I love Fatal Hotel!',
`account_created` varchar(50) NOT NULL,
`last_online` int(15) NOT NULL,
`online` enum('0','1') NOT NULL DEFAULT '0',
`ip_last` varchar(120) NOT NULL,
`ip_reg` varchar(120) NOT NULL,
`home_room` int(10) unsigned NOT NULL DEFAULT '0',
`daily_respect_points` int(11) NOT NULL DEFAULT '3',
`daily_pet_respect_points` int(11) NOT NULL DEFAULT '3',
`newbie_status` int(11) NOT NULL DEFAULT '0',
`is_muted` enum('0','1') NOT NULL DEFAULT '0',
`mutant_penalty` enum('0','1','2') NOT NULL DEFAULT '0',
`mutant_penalty_expire` int(11) NOT NULL DEFAULT '0',
`block_newfriends` enum('0','1') NOT NULL DEFAULT '0',
`hide_online` enum('0','1') NOT NULL DEFAULT '0',
`hide_inroom` enum('0','1') NOT NULL DEFAULT '0',
`vip` enum('0','1') NOT NULL DEFAULT '0',
`logged` int(11) NOT NULL,
`points` int(11) NOT NULL,
`country_code` varchar(20) NOT NULL,
`profile_status` enum('0','1','2') NOT NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED AUTO_INCREMENT=467835 ;
Thanks,
Josh
Here you go:
SELECT * FROM (SELECT country_code,count(country_code) AS 'Total' FROM `users`
GROUP BY country_code
ORDER BY 'Total' DESC) t LIMIT 50;
SQL Fiddle example
This might work:
SELECT country_code,count(country_code) as total FROM `users`
GROUP BY country_code
ORDER BY total
DESC LIMIT 50;

SQL UPDATE where in JOIN Clause

I have two tables: tt_news and tt_news_cat.
tt_news hast the columns tx_newscalendar_calendardate and a relation field for the category called category
the table tt_news_cat has an uid. The relation is an m:m relation. m:m is written in the table tt_news_cat_mm with thre fields uid_local (the news uid) and uid_foreign (the categories uid).
I would like to update a field in tt_news where the correesponding category uid is 12. My Update Clause in phpmyadmin looks as follows:
UPDATE b
SET `tx_newscalendar_calendardate` = `datetime`
FROM `tt_news` AS b
INNER JOIN `tt_news_cat` AS i
WHERE `i.category` = 12
What I am doing wrong here?
Thanks.
PS: table definitions:
#
# Table structure for table 'tt_news'
#
CREATE TABLE tt_news (
uid int(11) NOT NULL auto_increment,
pid int(11) DEFAULT '0' NOT NULL,
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
crdate int(11) unsigned DEFAULT '0' NOT NULL,
cruser_id int(11) unsigned DEFAULT '0' NOT NULL,
editlock tinyint(4) unsigned DEFAULT '0' NOT NULL,
deleted tinyint(3) unsigned DEFAULT '0' NOT NULL,
hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
starttime int(11) unsigned DEFAULT '0' NOT NULL,
endtime int(11) unsigned DEFAULT '0' NOT NULL,
fe_group varchar(100) DEFAULT '0' NOT NULL,
title text,
datetime int(11) unsigned DEFAULT '0' NOT NULL,
image text,
imagecaption text,
imagealttext text,
imagetitletext text,
related int(11) DEFAULT '0' NOT NULL,
short text,
bodytext mediumtext,
author varchar(255) DEFAULT '' NOT NULL,
author_email varchar(255) DEFAULT '' NOT NULL,
category int(11) DEFAULT '0' NOT NULL,
news_files text,
links text,
type tinyint(4) DEFAULT '0' NOT NULL,
page int(11) DEFAULT '0' NOT NULL,
keywords text,
archivedate int(11) DEFAULT '0' NOT NULL,
ext_url varchar(255) DEFAULT '' NOT NULL,
sys_language_uid int(11) DEFAULT '0' NOT NULL,
l18n_parent int(11) DEFAULT '0' NOT NULL,
l18n_diffsource mediumblob NOT NULL,
no_auto_pb tinyint(4) unsigned DEFAULT '0' NOT NULL,
t3ver_oid int(11) DEFAULT '0' NOT NULL,
t3ver_id int(11) DEFAULT '0' NOT NULL,
t3ver_wsid int(11) DEFAULT '0' NOT NULL,
t3ver_label varchar(30) DEFAULT '' NOT NULL,
t3ver_state tinyint(4) DEFAULT '0' NOT NULL,
t3ver_stage tinyint(4) DEFAULT '0' NOT NULL,
t3ver_count int(11) DEFAULT '0' NOT NULL,
t3ver_tstamp int(11) DEFAULT '0' NOT NULL,
t3_origuid int(11) DEFAULT '0' NOT NULL,
PRIMARY KEY (uid),
KEY parent (pid),
KEY t3ver_oid (t3ver_oid,t3ver_wsid),
KEY datetime (datetime)
);
#
# Table structure for table 'tt_news_cat'
#
CREATE TABLE tt_news_cat (
uid int(11) NOT NULL auto_increment,
pid int(11) DEFAULT '0' NOT NULL,
tstamp int(11) unsigned DEFAULT '0' NOT NULL,
crdate int(11) unsigned DEFAULT '0' NOT NULL,
hidden tinyint(4) unsigned DEFAULT '0' NOT NULL,
starttime int(11) unsigned DEFAULT '0' NOT NULL,
endtime int(11) unsigned DEFAULT '0' NOT NULL,
sorting int(11) unsigned DEFAULT '0' NOT NULL,
fe_group varchar(100) DEFAULT '0' NOT NULL,
title varchar(255) DEFAULT '' NOT NULL,
title_lang_ol varchar(255) DEFAULT '' NOT NULL,
image varchar(255) DEFAULT '' NOT NULL,
shortcut int(11) unsigned DEFAULT '0' NOT NULL,
shortcut_target varchar(255) DEFAULT '' NOT NULL,
deleted tinyint(3) unsigned DEFAULT '0' NOT NULL,
single_pid int(11) unsigned DEFAULT '0' NOT NULL,
parent_category int(11) unsigned DEFAULT '0' NOT NULL,
description text,
PRIMARY KEY (uid),
KEY parent (pid),
KEY parent_category (parent_category)
);
#
# Table structure for table 'tt_news_related_mm'
#
CREATE TABLE tt_news_related_mm (
uid_local int(11) DEFAULT '0' NOT NULL,
uid_foreign int(11) DEFAULT '0' NOT NULL,
sorting int(11) DEFAULT '0' NOT NULL,
tablenames varchar(255) DEFAULT '' NOT NULL,
KEY uid_local (uid_local),
KEY uid_foreign (uid_foreign)
);
#
# Table structure for table 'tt_news_cat_mm'
#
CREATE TABLE tt_news_cat_mm (
uid_local int(11) DEFAULT '0' NOT NULL,
uid_foreign int(11) DEFAULT '0' NOT NULL,
tablenames varchar(30) DEFAULT '' NOT NULL,
sorting int(11) DEFAULT '0' NOT NULL,
KEY uid_local (uid_local),
KEY uid_foreign (uid_foreign)
);

MySQL Extremely Slow Query

I am trying to learn about optimizations to MySQL, table engines and when to use them, etc.
I have a query that is running up against the time-out limit of 10 minutes and which needs to complete in seconds because its function is a user-generated report.
The Query:
SELECT em.employeeId, tsk.taskId
FROM employee em INNER JOIN
task tsk
ON tsk.employeeId = em.employeeId
WHERE em.employeeId <> 'Not Done'
AND tsk.employeeId (
SELECT employeeId FROM task
WHERE templateId
IN ( '5', '6', '7', '8' )
AND tsk.status = 'Done'
)
AND tsk.employeeId IN
(
SELECT employeeId FROM task
WHERE templateId IN
( '55', '56', '57', '58' )
AND status = 'Not Done'
)
Explain:
# id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, PRIMARY, tsk, ALL, , , , , 61326, Using where
1, PRIMARY, em, eq_ref, PRIMARY, PRIMARY, 4, newhire.tsk.employeeId, 1, Using index
3, DEPENDENT SUBQUERY, task, ALL, , , , , 61326, Using where
2, DEPENDENT SUBQUERY, task, ALL, , , , , 61326, Using where
The DB server uses MyISAM as default, so most schemas including this one are MyISAM.
I also realize that the text searches (status=Done or status LIKE 'Done') are adding a lot to the query.
EDIT1:
# Table, Create Table
employee, CREATE TABLE `employee` (
`employeeId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`lastName` varchar(255) NOT NULL,
`firstName` varchar(255) NOT NULL,
`applicantId` varchar(255) NOT NULL,
`fEmployeeId` varchar(255) DEFAULT NULL,
`opId` varchar(255) DEFAULT NULL,
`rehire` tinyint(3) unsigned NOT NULL DEFAULT '0',
`sDate` date DEFAULT NULL,
`oDate` date DEFAULT NULL,
`cDate` date DEFAULT NULL,
`additionalDate` date DEFAULT NULL,
`additionalType` varchar(255) DEFAULT NULL,
`processingDate` date DEFAULT NULL,
`created` datetime NOT NULL,
`recruiterId` int(10) unsigned NOT NULL,
`processorId` int(10) unsigned DEFAULT NULL,
`position` tinyint(3) unsigned NOT NULL DEFAULT '1',
`status` varchar(255) NOT NULL,
`campus` varchar(255) DEFAULT NULL,
`phone` varchar(255) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
`requisition` varchar(255) DEFAULT NULL,
`Position` varchar(255) DEFAULT NULL,
`department` varchar(255) DEFAULT NULL,
`jobClass` varchar(255) DEFAULT NULL,
`hiringManager` varchar(255) DEFAULT NULL,
`badge` varchar(255) DEFAULT NULL,
`currentAddress` varchar(255) DEFAULT NULL,
`holding` tinyint(3) unsigned DEFAULT '0',
PRIMARY KEY (`employeeId`)
) ENGINE=MyISAM AUTO_INCREMENT=3959 DEFAULT CHARSET=latin1
EDIT 2:
# Table, Create Table
task, CREATE TABLE `task` (
`taskId` int(10) unsigned NOT NULL AUTO_INCREMENT,
`templateId` int(10) unsigned NOT NULL,
`employeeId` int(10) unsigned NOT NULL,
`name` varchar(255) NOT NULL,
`description` text,
`naAvailable` tinyint(3) unsigned DEFAULT '0',
`fileRequired` tinyint(3) unsigned DEFAULT '0',
`fileHrCatalog` int(10) unsigned DEFAULT NULL,
`quickFileName` varchar(255) DEFAULT NULL,
`fileUploaded` tinyint(3) unsigned DEFAULT '0',
`fileExt` varchar(255) DEFAULT NULL,
`level` tinyint(3) unsigned NOT NULL,
`status` varchar(255) NOT NULL,
`due` date DEFAULT NULL,
`daysDue` int(10) unsigned DEFAULT NULL,
`routeIncentives` tinyint(3) unsigned DEFAULT '0',
`requiresAudit` tinyint(3) unsigned DEFAULT '0',
`auditStatus` varchar(255) DEFAULT NULL,
`auditUser` int(10) unsigned DEFAULT NULL,
`auditDate` datetime DEFAULT NULL,
`stampOption` tinyint(3) unsigned DEFAULT '0',
`done` tinyint(3) unsigned DEFAULT '0',
`doneBy` int(10) unsigned DEFAULT NULL,
`doneWhen` datetime DEFAULT NULL,
`sortOrder` tinyint(3) unsigned NOT NULL DEFAULT '255',
PRIMARY KEY (`taskId`),
KEY `status` (`status`,`templateId`)
) ENGINE=MyISAM AUTO_INCREMENT=176802 DEFAULT CHARSET=latin1
I would write the query as below, but to help the optimization, have a covering indexes on your tables.
Employee table -- index on ( status, employeeID )
Task table -- index on ( employeeid, templateid, status )
By the first join, you are prequalifying to get the first task as a "Done" status.
The second join is looking for the OTHER task you are interested in that is NOT Done.
Doing subqueries (especially correlated sub queries) can be harder on performance. By doing a JOIN, it's either there or its not...
SELECT
em.employeeId,
tsk.taskId
FROM
employee em
INNER JOIN task tsk1
ON em.employeeId = tsk1.employeeId
AND tsk1.templateID in ( '5', '6', '7', '8' )
AND tsk1.status = 'Done'
INNER JOIN task tsk2
ON em.employeeId = tsk2.employeeId
AND tsk2.templateID in ( '55', '56', '57', '58' )
AND tsk2.status = 'Not Done'
WHERE
em.status <> 'Not Done'
Your first change should be to create an index on task that covers both the status and templateId columns:
ALTER TABLE task ADD INDEX (status, templateId);
That'll prevent the full-table scans of 61326 rows each time that table is accessed in your query.
Also, it looks like you might have made a typo here:
SELECT employeeId FROM task
WHERE templateId
IN ( '5', '6', '7', '8' )
AND tsk.status = 'Done'
That tsk.status should be just status like the 2nd subquery.