SQL INNER join take too long to execute - mysql

I have below sql query that take too long to execute, please there is an alternative for inner joins to resolve my issue?, because when I remove 3 or 4 joins the query is executed faster.
SELECT p.first_name, p.last_name, p.x, p.dob,'name', w.id_table1, w.type, w.stype, w.ploc, w.dat, w.created_at, av.item as table1_edge , av1.item as sdf ,av2.item as sd, av3.item as odor, av4.item as xz, av5.value as xxx , av9.item as cc, av10.item as cxz
FROM table1 w
INNER JOIN table2 a ON w.id_table1 = a.table1_id_table1
INNER JOIN table3 av ON a.id_table2 = av.id_table3 and av.sub_group = 'x1'
INNER JOIN table3 av1 ON a.id_table2 = av1.id_table3 and av1.sub_group = 'x2'
INNER JOIN table3 av2 ON a.id_table2 = av2.id_table3 and av2.sub_group = 'x3'
INNER JOIN table3 av3 ON a.id_table2 = av3.id_table3 and av3.sub_group = 'x4'
INNER JOIN table3 av4 ON a.id_table2 = av4.id_table3 and av4.sub_group = 'x5'
INNER JOIN table3 av5 ON a.id_table2 = av5.id_table3 and av5.sub_group = 'x6' and av6.item like 's%'
INNER JOIN table3 av6 ON a.id_table2 = av6.id_table3 and av6.sub_group = 'x7' and av6.item like 'x%'
INNER JOIN table3 av7 ON a.id_table2 = av7.id_table3 and av7.sub_group = 'x8' and av6.item like 'z%'
INNER JOIN table3 av8 ON a.id_table2 = av8.id_table3 and av8.sub_group = 'x9' and av6.item like 'y%'
INNER JOIN table3 av9 ON a.id_table2 = av9.id_table3 and av9.sub_group = 'x10'
INNER JOIN table3 av10 ON a.id_table2 = av10.id_table3 and av10.sub_group = 'x11'
INNER JOIN table0 p ON w.table0_id_table0 = p.id_table0
where w.created_at between '1991-12-09 00:00:00' and now() and user_id_user = 4
data:
table0
first_namelast_namedob...
table1id_table1 type stype ...

Have you tried to use subqueries instead for the inner joins that take longer to execute?
Example:
select a.id, b.id, c.id
from table a
inner join (
select id
from tableb
where b = 'x1'
) as b on b.id = a.id
inner join (
select id
from tablec
where c = 'x2'
) as c on c.id = a.id

Maybe you can make you query simpler like this:
SELECT p.first_name, p.last_name, p.x, p.dob,'name',
w.id_table1, w.type, w.secondary_type, w.primary_location,
w.onset, w.created_at, av.item,
IF(av.sub_group='x1', 1, 0) as val_x1,
IF(av.sub_group='x2', 1, 0) as val_x2,
IF(av.sub_group='x3', 1, 0) as val_x3,
..........
IF(av.sub_group='x11', 1, 0) as val_x11
FROM table1 w
INNER JOIN table2 a ON w.id_table1 = a.table1_id_table1
left join table3 av on a.id_table2 = av.id_table3
INNER JOIN table0 p ON w.table0_id_table0 = p.id_table0
where w.created_at between '1991-12-09 00:00:00'
and now() and user_id_user = 4
and ( (av.sub_group in ('x1', 'x2', 'x3', 'x4', 'x5', 'x10', 'x11'))
or (av.sub_group='x6' and av.item like 's%')
or (av.sub_group='x7' and av.item like 'x%')
or (av.sub_group='x8' and av.item like 'z%')
or (av.sub_group='x9' and av.item like 'y%')
)
We make just one JOIN with table table3 and move all conditions into where clause. With val_x1 .... val_x11 we can know which one value we have at av.item.

You seem to be storing things in an EAV format (entity-attribute-value). If you don't understand what this means, you can review the definitions on Wikipedia.
One solution is to use aggregation:
SELECT p.first_name, p.last_name, p.x, p.dob, 'name',
w.id_table1, w.type, w.secondary_type, w.primary_location,
w.onset, w.created_at,
MAX(CASE WHEN av.sub_group = 'x1' THEN av.item END) as table1_edge,
MAX(CASE WHEN av.sub_group = 'x1' THEN av.item END) as sdf,
. . .
FROM table1 w INNER JOIN
table2 a
ON w.id_table1 = a.table1_id_table1 INNER JOIN
table3 av
ON a.id_table2 = av.id_table3
WHERE av.sub_group IN ('x1', 'x2', . . . ) AND
w.created_at between '1991-12-09' and now() AND
user_id_user = 4
GROUP BY p.first_name, p.last_name, p.x, p.dob,
w.id_table1, w.type, w.secondary_type, w.primary_location, w.onset, w.created_at;
You also want appropriate indexes. I am guessing these are table1(user_id_user, created_at, id_table1) and table3(id_table3, sub_group, item).

Related

How not to include the ID in the result of the query when using Left Join

Im trying to populate my listview with data from three tables stu_tblbasicinfo,stu_tblfam and stu_tbleducbackground
they all have the same id which is TagID
Select A.TagID , A.Surname, A.Firstname, A.Middlename, A.Course, A.Year, B.ZipCode,
B.Province, B.Municipality, B.Barangay, A.ContactNo, A.EmailAddress, A.Birthdate,
A.Age, A.Birthplace, A.Religion, A.Gender, A.CivilStatus, A.Spouse, C.Mothersname,
C.M_occupation, C.M_Number, C.Fathersname, C.F_Occupation, C.F_Number,
C.GuardianName, C.G_Occupation, C.G_Number, D.Elementary, D.E_Years, D.JuniorHigh,
D.J_Years, Seniorhigh, D.S_Years
from stu_tblbasicinfo As A
left join stu_tblzipcode As B
on A.Barangay = B.Barangay
inner join stu_tblfam As C
ON A.TagID = C.TagID
inner join stu_tbleducbackground As D
ON A.TagID = D.TagID
My code works but the problem is it displays 3 TagID.
The result is like this
TagID(studentinfo table),Surname,Firstname,Middlename,TagID(familyBackground table),MName,FName,Gname,TagID(EducBackground table),Elementary,E_years,JuniorHigh,J_Years,SeniorHigh,S_Years
How can I make the result in this format?
TagID,Surname,Firstname,Middlename,Mname,Fname,Gname,Elementary,E.Years,JuniorHigh,J_Years,SeniorHigh,S_Years
Just this:
Select
A.TagID ,
A.Surname,
A.Firstname,
A.Middlename,
C.Mothersname,
C.Fathersname,
C.GuardianName,
D.Elementary,
D.E_Years,
D.JuniorHigh,
D.J_Years,
D.Seniorhigh,
D.S_Years
from stu_tblbasicinfo As A
left join stu_tblzipcode As B
on A.Barangay = B.Barangay
inner join stu_tblfam As C
ON A.TagID = C.TagID
inner join stu_tbleducbackground As D
ON A.TagID = D.TagID

how understand the relation between parent query and subquery in mysql?

Someone please explain the difference between parent query and sub query? How do I understand?
e.g:
SELECT
ra.ID id,
ra.ACCOUNT_ID accountId,
ef.REAL_NAME realName,
a.MOBILE mobile,
sps.`NAME` siteName,
ef.CREATE_TIME createTime,
a.`STATUS` status,
ra.`STATUS` siteStatus,
(
SELECT
aif.APPROVER_NAME
FROM
audit_info aif
WHERE
aif.TARGET_ID = a.ID AND af.AUDIT_TYPE=2
AND aif.CREATE_TIME = (
SELECT
MAX(af.CREATE_TIME)
FROM
audit_info af
WHERE
af.TARGET_ID = a.ID AND af.AUDIT_TYPE=2
)
) AS approverName
FROM
account a
INNER JOIN site_relation_account ra ON ra.ACCOUNT_ID = a.ID
INNER JOIN account_ext ef ON ra.ACCOUNT_ID = ef.ACCOUNT_ID
INNER JOIN service_provider_site sps ON sps.ID = ra.SITE_ID
LEFT JOIN audit_info af ON af.TARGET_ID = ef.ACCOUNT_ID
WHERE ra.ACCOUNT_TYPE = 2

how to GROUP_CONCAT with Concat

Product name supplier
A Su1
A Su1
A Su2
B Su1
C Su3
I want like this
A - su1, A-su2, B-su1, C-su3
Query:
SELECT
vtiger_salesorder.salesorder_no,
(Select
group_concat(DISTINCT concat(vtiger_products.productname, '-', vtiger_vendor.vendorname ) SEPARATOR ', ')
FROM
vtiger_salesorder
LEFT Join vtiger_inventoryproductrel ON vtiger_salesorder.salesorderid = vtiger_inventoryproductrel.id
inner Join vtiger_products ON vtiger_products.productid = vtiger_inventoryproductrel.productid
inner Join softMax_SalesOrderVendorInfo ON softMax_SalesOrderVendorInfo.salesorderid = vtiger_salesorder.salesorderid
LEFT JOIN vtiger_vendor ON softMax_SalesOrderVendorInfo.vendorid = vtiger_vendor.vendorid
where (vtiger_salesorder.salesorderid = vtiger_inventoryproductrel.id
AND vtiger_salesorder.salesorderid = vtiger_crmentity.crmid
and (softMax_SalesOrderVendorInfo.status = '0') )Group by vtiger_salesorder.salesorderid Limit 0,1) As SuName1
FROM
vtiger_salesorder
INNER JOIN vtiger_inventoryproductrel ON vtiger_salesorder.salesorderid = vtiger_inventoryproductrel.id
Inner Join vtiger_crmentity ON vtiger_salesorder.salesorderid = vtiger_crmentity.crmid
Order by vtiger_salesorder.salesorder_no
Given your original data, you can simply do this with something like:
select distinct group_concat(ProductName, '-', Supplier separator ', ')
from table t;
I have no idea what the query has to do with the question, because you already seem to have the data in the appropriate format.

slow query with joins

Please am having difficulty in optimizing this query. What am trying to achieve is to join about 8 tables, of which only about 3 of the tables contains large data (1.5m records). This query returns expected records but is taking 1min to run which is bad.
I know it can be optimized to perform far better, pls i need assistance from you experts. I have index on the fields used for join already.
SELECT topic_id,
topic_title,
unit_name_abbrev,
sch_name_abbrev,
picture_small_url AS thumbnail,
profile_pix_upload_path,
first_name,
last_name,
topic_poster,
topic_replies,
topic_views,
topic_last_post_time AS topic_post_time,
sch_sub_forum_id
FROM (_sch_forum_topics
INNER JOIN _users
ON ( _users.userid = _sch_forum_topics.topic_poster )
INNER JOIN _profile
ON _profile.userid = _users.userid
INNER JOIN _class
ON _users.classid = _class.classid
INNER JOIN _level
ON _class.level_id = _level.id
INNER JOIN _unit
ON _class.unitid = _unit.unitid
INNER JOIN _department
ON _unit.deptid = _department.deptid
INNER JOIN _faculty
ON _department.facid = _faculty.facid
INNER JOIN _university
ON _faculty.schid = _university.schid)
WHERE _sch_forum_topics.sch_sub_forum_id = 4
ORDER BY _sch_forum_topics.topic_last_post_time DESC
LIMIT 0, 15
Try to filter before making JOIN's.
SELECT topic_id,
topic_title,
unit_name_abbrev,
sch_name_abbrev,
picture_small_url AS thumbnail,
profile_pix_upload_path,
first_name,
last_name,
topic_poster,
topic_replies,
topic_views,
topic_last_post_time AS topic_post_time,
sch_sub_forum_id
FROM
( select * FROM sch_forum_topics WHERE sch_sub_forum_id = 4
ORDER BY topic_last_post_time DESC
LIMIT 0, 15 ) main
INNER JOIN _users
ON ( _users.userid = main.topic_poster )
INNER JOIN _profile
ON _profile.userid = _users.userid
INNER JOIN _class
ON _users.classid = _class.classid
INNER JOIN _level
ON _class.level_id = _level.id
INNER JOIN _unit
ON _class.unitid = _unit.unitid
INNER JOIN _department
ON _unit.deptid = _department.deptid
INNER JOIN _faculty
ON _department.facid = _faculty.facid
INNER JOIN _university
ON _faculty.schid = _university.schid);

MySQL Update table with sum value of another table

I have a query that I can't seem to manipulate to work in a SUM function in MySQL:
Here is what I want:
UPDATE account_seeds AS a
INNER JOIN b AS b ON b.accountID = a.accountID AND a.areaID = b.areaID
INNER JOIN b_seed AS s ON s.buildingID = b.buildingID
INNER JOIN seed_class AS c ON c.seedID = s.seedID
SET a.amount = a.amount + SUM(s.amount)
WHERE b.status='active' AND a.seedID = s.seedID
Now it obviously won't let me use the SUM in the update without separating it. I have tried joining select queries but can't quite get my head around it. The basic premise being that I have multiple buildings(rows) that has a seed value that will increase total seeds of that type in the area for a particular account. Without the sum it only updates one of the buildings that has a matching seed value
UPDATE
account_seeds AS a
INNER JOIN
( SELECT b.accountID, b.areaID, s.seedID
, SUM(s.amount) AS add_on
FROM b AS b
INNER JOIN b_seed AS s
ON s.buildingID = b.buildingID
INNER JOIN seed_class AS c
ON c.seedID = s.seedID
WHERE b.status = 'active'
GROUP BY b.accountID, b.areaID, s.seedID
) AS g
ON g.accountID = a.accountID
AND g.areaID = a.areaID
AND g.seedID = a.seedID
SET
a.amount = a.amount + g.add_on ;
Maybe you can use a nested query:
UPDATE account_seeds AS a
INNER JOIN b AS b ON b.accountID = a.accountID AND a.areaID = b.areaID
INNER JOIN b_seed AS s ON s.buildingID = b.buildingID
INNER JOIN seed_class AS c ON c.seedID = s.seedID
SET a.amount = a.amount + (SELECT SUM(amount) FROM b_seed)
WHERE b.status='active' AND a.seedID = s.seedID
Can you try that?