Optimise a MYSQL query based on users and usermeta table - mysql

the tables
the query
SELECT
u.ID AS _ctbUserId,
umRef.meta_value AS _ctbRef,
umThumbnail.meta_value AS _ctbThumbnail,
umShortText.meta_value AS _ctbShortText,
umLanguages.meta_value AS _ctbLanguages,
umKeywords.meta_value AS _ctbKeywords,
umNickname.meta_value AS _ctbNickname,
umChatSessionGuid.meta_value AS _ctbChatSessionGuid,
umChatSessionStatus.meta_value AS _ctbChatSessionStatus,
umChatSessionStatusVisual.meta_value AS _ctbChatSessionStatusVisual,
umChatSessionMaxUsers.meta_value AS _ctbChatSessionMaxUsers,
umChatSessionLastChanged.meta_value AS _ctbChatSessionLastChanged,
umChatSessionTpm.meta_value AS _ctbChatSessionTpm,
umChatEnableCam.meta_value AS _ctbChatEnableCam,
umMessenger.meta_value AS _ctbMessenger,
umMessengerTokensPerMessage.meta_value AS _ctbMessengerTokensPerMessage,
umCallSessionStatus.meta_value AS _ctbCallSessionStatus,
umCallSessionStatusVisual.meta_value AS _ctbCallSessionStatusVisual,
umCallSessionStatusLastChanged.meta_value AS _ctbCallSessionLastChanged,
umCallSessionTpm.meta_value AS _ctbCallSessionTpm
FROM chattabai_users AS u
LEFT JOIN chattabai_usermeta AS umRole ON umRole.user_id = u.ID AND umRole.meta_key = "chattabai_capabilities"
LEFT JOIN chattabai_usermeta AS umRef ON umRef.user_id = u.ID AND umRef.meta_key = "_ctbRef"
LEFT JOIN chattabai_usermeta AS umThumbnail ON umThumbnail.user_id = u.ID AND umThumbnail.meta_key = "_ctbThumbnail"
LEFT JOIN chattabai_usermeta AS umShortText ON umShortText.user_id = u.ID AND umShortText.meta_key = "_ctbShortText"
LEFT JOIN chattabai_usermeta AS umLanguages ON umLanguages.user_id = u.ID AND umLanguages.meta_key = "_ctbLanguages"
LEFT JOIN chattabai_usermeta AS umKeywords ON umKeywords.user_id = u.ID AND umKeywords.meta_key = "_ctbKeywords"
LEFT JOIN chattabai_usermeta AS umNickname ON umNickname.user_id = u.ID AND umNickname.meta_key = "_ctbNickname"
LEFT JOIN chattabai_usermeta AS umChatSessionGuid ON umChatSessionGuid.user_id = u.ID AND umChatSessionGuid.meta_key = "_ctbChatSessionGuid"
LEFT JOIN chattabai_usermeta AS umChatSessionStatus ON umChatSessionStatus.user_id = u.ID AND umChatSessionStatus.meta_key = "_ctbChatSessionStatus"
LEFT JOIN chattabai_usermeta AS umChatSessionStatusVisual ON umChatSessionStatusVisual.user_id = u.ID AND umChatSessionStatusVisual.meta_key = "_ctbChatSessionStatusVisual"
LEFT JOIN chattabai_usermeta AS umChatSessionMaxUsers ON umChatSessionMaxUsers.user_id = u.ID AND umChatSessionMaxUsers.meta_key = "_ctbChatSessionMaxUsers"
LEFT JOIN chattabai_usermeta AS umChatSessionLastChanged ON umChatSessionLastChanged.user_id = u.ID AND umChatSessionLastChanged.meta_key = "_ctbChatSessionLastChanged"
LEFT JOIN chattabai_usermeta AS umChatSessionTpm ON umChatSessionTpm.user_id = u.ID AND umChatSessionTpm.meta_key = "_ctbChatSessionTpm"
LEFT JOIN chattabai_usermeta AS umChatEnableCam ON umChatEnableCam.user_id = u.ID AND umChatEnableCam.meta_key = "_ctbChatEnableCam"
LEFT JOIN chattabai_usermeta AS umMessenger ON umMessenger.user_id = u.ID AND umMessenger.meta_key = "_ctbMessenger"
LEFT JOIN chattabai_usermeta AS umMessengerTokensPerMessage ON umMessengerTokensPerMessage.user_id = u.ID AND umMessengerTokensPerMessage.meta_key = "_ctbMessengerTokensPerMessage"
LEFT JOIN chattabai_usermeta AS umCallSessionStatus ON umCallSessionStatus.user_id = u.ID AND umCallSessionStatus.meta_key = "_ctbCallSessionStatus"
LEFT JOIN chattabai_usermeta AS umCallSessionStatusVisual ON umCallSessionStatusVisual.user_id = u.ID AND umCallSessionStatusVisual.meta_key = "_ctbCallSessionStatusVisual"
LEFT JOIN chattabai_usermeta AS umCallSessionStatusLastChanged ON umCallSessionStatusLastChanged.user_id = u.ID AND umCallSessionStatusLastChanged.meta_key = "_ctbCallSessionLastChanged"
LEFT JOIN chattabai_usermeta AS umCallSessionTpm ON umCallSessionTpm.user_id = u.ID AND umCallSessionTpm.meta_key = "_ctbCallSessionTpm"
WHERE umRole.meta_value LIKE 'a: 1: {s: 8:\"employee\";b:1;}'
AND (umChatSessionStatus.meta_value REGEXP 'online|inConversation|pause|offline' OR umCallSessionStatus.meta_value REGEXP 'online|inConversation|pause|offline')
AND umLanguages.meta_value REGEXP ''
AND umKeywords.meta_value REGEXP ''
ORDER BY FIELD(umChatSessionStatus.meta_value, 'online,inConversation,pause,offline'), FIELD(umCallSessionStatus.meta_value, 'online,inConversation,pause,offline')
LIMIT 0, 20
This is from a Wordpress database. As Wordpress uses usermeta data this is the way of storing the user data. ( https://developer.wordpress.org/plugins/users/working-with-user-metadata/ )
This query takes up to 1500MS to run on with a limit of 20 profiles. Any recommendations to improve this?
Output

Related

MySQL syntax error [Left Join]

So i've got this query below and it's giving me a syntax error. I will show the error below the query.
Please check below:
SELECT g.fullname, g.id as guardian_id, g.email, g.email_2, s.title, s.domain, d.device_id as device, d.os, gf.booking_open_notified, gf.days_notified_7, gf.days_notified_3, gf.day_notified, s.id as school_id, p.firstname, p.surname
FROM guardian as g
LEFT JOIN guardian_form as gf ON gf.school_id = g.school_id
LEFT JOIN school as s ON s.id = g.school_id
LEFT JOIN school_design as sd ON sd.school_id = s.id
LEFT JOIN device as d ON d.school_id = s.id AND d.guardian_id = g.id
(
LEFT JOIN pupil as p ON p.school_id = s.id AND
(
p.grade_id = gf.grade_id
OR p.grade_id = gf.grade_id_2
OR p.grade_id = gf.grade_id_3
OR p.grade_id = gf.grade_id_4
OR p.grade_id = gf.grade_id_5
OR p.grade_id = gf.grade_id_6
OR p.grade_id = gf.grade_id_7
OR p.grade_id = gf.grade_id_8
OR p.grade_id = gf.grade_id_9
OR p.grade_id = gf.grade_id_10
)
) OR (
LEFT JOIN guardian_form_group as gfg ON gfg.guardian_form_id = gf.id
LEFT JOIN pupil_group as pg ON pg.group_id = gfg.group_id
LEFT JOIN pupil as p ON p.id = pg.pupil_id AND pg.school_id = s.id
)
WHERE (
gf.booking_open_notified != 1
OR gf.days_notified_7 != 1
OR gf.days_notified_3 != 1
OR gf.day_notified != 1
)
AND gf.active = 1
AND sd.disable_parents_evening_notification_and_email = 0
GROUP BY gf.id, p.id
LIMIT 20
Error:
Error SQL query: Documentation
SELECT g.fullname, g.id as guardian_id, g.email, g.email_2, s.title,
s.domain, d.device_id as device, d.os, gf.booking_open_notified,
gf.days_notified_7, gf.days_notified_3, gf.day_notified, s.id as
school_id, p.firstname, p.surname FROM guardian as g LEFT JOIN
guardian_form as gf ON gf.school_id = g.school_id LEFT JOIN school as
s ON s.id = g.school_id LEFT JOIN school_design as sd ON sd.school_id
= s.id LEFT JOIN device as d ON d.school_id = s.id AND d.guardian_id = g.id
(
LEFT JOIN pupil as p ON p.school_id = s.id AND
(
p.grade_id = gf.grade_id
OR p.grade_id = gf.grade_id_2
OR p.grade_id = gf.grade_id_3
OR p.grade_id = gf.grade_id_4
OR p.grade_id = gf.grade_id_5
OR p.grade_id = gf.grade_id_6
OR p.grade_id = gf.grade_id_7
OR p.grade_id = gf.grade_id_8
OR p.grade_id = gf.grade_id_9
OR p.grade_id = gf.grade_id_10
)
) OR
MySQL said: Documentation
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near
'JOIN pupil as p ON p.school_id = s.id AND
(
p.grade_id = gf.' at line 8
Your syntax IS LIKE
SELECT listOfColumns FROM table1 LEFT JOIN table2 (LEFT JOIN table3) OR (LEFT JOIN table4)
Why are you trying TO USE 'OR' for joining ? This is not supported. Try improving your ON conditions if you want to filter out the tables

Show rows with SUM of two columns with subqueries and multiple JOINS

Hello I'm about to explode.. I have been trying for hours now getting this to work. I have found different solutions for others and tried to rewrite it so it fits to my script but it just wont work as it should.
With reference from Barmar to this post: Join tables with SUM issue in MYSQL
I have got a little way forward but I can't get it to print out what it should.
I have tried a lot of variant and moved around the JOINS etc. but without any luck. This is the query that gets nearest my wanted result:
SELECT
qs.statistic_ref_id,
qs.question_id,
SUM(qs.correct_count) AS count_correct,
qs2.total_count_2 AS total_count,
sr.user_id,
sr.quiz_id,
qq.title AS ny_titel,
qq.category_id,
SUBSTRING(qq.title,1,4) AS get_type_number,
pl.points
FROM pro_quiz_statistic AS qs
JOIN pro_quiz_statistic_ref sr ON sr.statistic_ref_id = qs.statistic_ref_id
JOIN pro_quiz_question qq ON qq.id = qs.question_id
JOIN user_points_log pl ON pl.quiz_id = sr.quiz_id AND pl.user_id = '$user_id'
JOIN ( SELECT
qs3.statistic_ref_id,
qs3.question_id,
SUM(qs3.correct_count + qs3.incorrect_count) AS total_count_2,
sr3.user_id,
sr3.quiz_id,
qq3.title AS ny_titel_2,
qq3.category_id,
SUBSTRING(qq3.title,1,4) AS get_type_number_2,
pl3.points
FROM pro_quiz_statistic AS qs3
JOIN pro_quiz_statistic_ref sr3 ON sr3.statistic_ref_id = qs3.statistic_ref_id
JOIN pro_quiz_question qq3 ON qq3.id = qs3.question_id
JOIN user_points_log pl3 ON pl3.quiz_id = sr3.quiz_id AND pl3.user_id = '$user_id'
WHERE sr3.user_id = '$user_id' AND
qq3.category_id = '3'
GROUP BY get_type_number_2 ORDER BY qs3.question_id
) qs2 ON qs2.statistic_ref_id = sr.statistic_ref_id
WHERE sr.user_id = '$user_id' AND
qq.category_id = '3'
GROUP BY get_type_number ORDER BY qs.question_id
You can see the outcome of this result in this picture (to the right):
whats_printing.jpg
The two first tables is pictures of the queries separately and is what it should print out. Just in one query.
I have tried with these two subqueries:
SELECT
qs.statistic_ref_id,
qs.question_id,
qs2.correct_count AS count_correct,
qs3.total_count_2 AS total_count,
sr.user_id,
sr.quiz_id,
qq.category_id,
SUBSTRING(qq.title,1,4) AS get_type_number,
pl.points
FROM pro_quiz_statistic AS qs
JOIN pro_quiz_statistic_ref sr ON sr.statistic_ref_id = qs.statistic_ref_id
JOIN pro_quiz_question qq ON qq.id = qs.question_id
JOIN user_points_log pl ON pl.quiz_id = sr.quiz_id AND pl.user_id = '$user_id'
JOIN (
SELECT
qs2.statistic_ref_id,
qs2.question_id,
SUM(qs2.correct_count) AS count_correct_2,
sr2.user_id,
sr2.quiz_id,
qq2.category_id,
SUBSTRING(qq2.title,1,4) AS get_type_number_2,
pl2.points
FROM pro_quiz_statistic AS qs2
JOIN pro_quiz_statistic_ref sr2 ON sr2.statistic_ref_id = qs2.statistic_ref_id
JOIN pro_quiz_question qq2 ON qq2.id = qs2.question_id
JOIN user_points_log pl2 ON pl2.quiz_id = sr2.quiz_id AND pl2.user_id = '$user_id'
WHERE sr2.user_id = '$user_id' AND
qq2.category_id = '3'
GROUP BY get_type_number_2
ORDER BY qs2.question_id
) qs2 ON qs2.statistic_ref_id = qs.statistic_ref_id
JOIN ( SELECT
qs3.statistic_ref_id,
qs3.question_id,
SUM(qs3.correct_count + qs3.incorrect_count) AS total_count_2,
sr3.user_id,
sr3.quiz_id,
qq3.category_id,
SUBSTRING(qq3.title,1,4) AS get_type_number_3,
pl3.points
FROM pro_quiz_statistic AS qs3
JOIN pro_quiz_statistic_ref sr3 ON sr3.statistic_ref_id = qs3.statistic_ref_id
JOIN pro_quiz_question qq3 ON qq3.id = qs3.question_id
JOIN user_points_log pl3 ON pl3.quiz_id = sr3.quiz_id AND pl3.user_id = '$user_id'
WHERE sr3.user_id = '$user_id' AND
qq3.category_id = '3'
GROUP BY get_type_number_3
ORDER BY qs3.question_id
) qs3 ON qs3.statistic_ref_id = qs.statistic_ref_id
WHERE sr.user_id = '$user_id' AND
qq.category_id = '3'
GROUP BY get_type_number
ORDER BY qs.question_id
but then it's not printing anything. This works:
SELECT
qs.statistic_ref_id,
qs.question_id,
SUM(qs.correct_count) AS count_correct,
sr.user_id,
sr.quiz_id,
qq.title AS ny_titel,
qq.category_id,
SUBSTRING(qq.title,1,4) AS get_type_number,
pl.points
FROM pro_quiz_statistic AS qs
JOIN pro_quiz_statistic_ref sr ON sr.statistic_ref_id = qs.statistic_ref_id
JOIN pro_quiz_question qq ON qq.id = qs.question_id
JOIN user_points_log pl ON pl.quiz_id = sr.quiz_id AND pl.user_id = '$user_id'
WHERE sr.user_id = '$user_id' AND
qq.category_id = '3'
GROUP BY get_type_number ORDER BY qs.question_id
And also this (if I run them separately):
SELECT
qs.statistic_ref_id,
qs.question_id,
SUM(qs.correct_count + qs.incorrect_count) AS count_correct,
sr.user_id,
sr.quiz_id,
qq.title AS ny_titel,
qq.category_id,
SUBSTRING(qq.title,1,4) AS get_type_number,
pl.points
FROM pro_quiz_statistic AS qs
JOIN pro_quiz_statistic_ref sr ON sr.statistic_ref_id = qs.statistic_ref_id
JOIN pro_quiz_question qq ON qq.id = qs.question_id
JOIN user_points_log pl ON pl.quiz_id = sr.quiz_id AND pl.user_id = '$user_id'
WHERE sr.user_id = '$user_id' AND
qq.category_id = '3'
GROUP BY get_type_number ORDER BY qs.question_id
But how can I combine those two to one query?

Mysql update using select

I'm trying to update the fields by using below query. What is the error in below query ?
MySQL said: Documentation
1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use
near 'FROM orders cl' at line 2
update hedging SET
Dept = concat(RIGHT( dpt.DeptName,2),LEFT( grp.GroupName,3),LEFT( st.Login,3)),
OrderNo = cl.OrderNo,Client = cn.ShortName,
Currency = cur.Notation, SellingAmount = pto.PIAmount ,
BuyingAmount = pto.POAmount
FROM orders cl
left join client cn on cl.ClientID = cn.ClientID
inner join department dpt on cl.DeptID = dpt.DeptID
inner join supplier sp on cl.SupplierID = sp.SupplierId
left join staff st on st.StaffID = cl.SalesPerson
left join pipo_total pto on pto.OrderNo = cl.OrderNo
inner join groups grp on cl.GroupID = grp.GroupID
left join currency cur on cur.CurrencyID= cl.SellCurrencyID
left join hedging hed on hed.OrderNo = cl.OrderNo)
where cur.Notation <> 'USD' and cl.OrderType = '1' and hed.OrderNo = cl.OrderNo
Try 1
update orders cl
left join client cn on cl.ClientID = cn.ClientID
inner join department dpt on cl.DeptID = dpt.DeptID
inner join supplier sp on cl.SupplierID = sp.SupplierId
left join staff st on st.StaffID = cl.SalesPerson
left join pipo_total pto on pto.OrderNo = cl.OrderNo
inner join groups grp on cl.GroupID = grp.GroupID
left join currency cur on cur.CurrencyID= cl.SellCurrencyID
left join hedging hed on hed.OrderNo = cl.OrderNo
SET hed.Dept = concat(RIGHT( dpt.DeptName,2),LEFT( grp.GroupName,3),LEFT( st.Login,3))
,hed.OrderNo = cl.OrderNo
,hed.Client = cn.ShortName
,hed.Currency = cur.Notation
,hed.SellingAmount = pto.PIAmount
,hed.BuyingAmount = pto.POAmount
where cur.Notation <> 'USD' and cl.OrderType = '1' and hed.OrderNo = cl.OrderNo
UPDATE with multiple tables should be something like this
UPDATE table1 t1
INNER JOIN table2 t2 ON t1.ID = t2.ID
SET t1.value = [value]
Edit: Your updated query
update orders cl
left join client cn on cl.ClientID = cn.ClientID
inner join department dpt on cl.DeptID = dpt.DeptID
inner join supplier sp on cl.SupplierID = sp.SupplierId
left join staff st on st.StaffID = cl.SalesPerson
left join pipo_total pto on pto.OrderNo = cl.OrderNo
inner join groups grp on cl.GroupID = grp.GroupID
left join currency cur on cur.CurrencyID= cl.SellCurrencyID
left join hedging hed on hed.OrderNo = cl.OrderNo)
SET Dept = concat(RIGHT( dpt.DeptName,2),LEFT( grp.GroupName,3),LEFT( st.Login,3))
,OrderNo = cl.OrderNo
,Client = cn.ShortName
,Currency = cur.Notation
,SellingAmount = pto.PIAmount
,BuyingAmount = pto.POAmount
where cur.Notation <> 'USD' and cl.OrderType = '1' and hed.OrderNo = cl.OrderNo

specifying preferred results for GROUP BY values

I have the following (simplified) query:
SELECT
u.idnumber AS user_idnumber,
sst_status.value AS scorm_status,
sst_starttime.value AS scorm_starttime,
sst_duration.value AS scorm_duration,
sst_score.value AS scorm_score,
u.id as uid,
s.id as scormid,
ss.id as ssid
FROM {user} u
LEFT JOIN {prog_user_assignment} prua ON prua.userid = u.id
LEFT JOIN {prog} pr ON prua.programid = pr.id
LEFT JOIN {prog_courseset} prcs ON prcs.programid = pr.id
LEFT JOIN {prog_courseset_course} prcsc ON prcsc.coursesetid = prcs.id
LEFT JOIN {course} c ON prcsc.courseid = c.id
LEFT JOIN {scorm} s ON s.id = cm.instance
LEFT JOIN {scorm_scoes} ss ON ss.scorm = s.id
LEFT JOIN {scorm_scoes_track} sst_status
ON sst_status.userid = u.id
AND sst_status.scormid = ss.scorm
AND sst_status.element = 'cmi_core.lesson_status'
AND sst_status.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_starttime
ON sst_starttime.userid = u.id
AND sst_starttime.scormid = ss.scorm
AND sst_starttime.element = 'x.start.time'
AND sst_starttime.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_duration
ON sst_duration.userid = u.id
AND sst_duration.scormid = ss.scorm
AND sst_duration.element = 'cmi.core.total_time'
AND sst_duration.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_score
ON sst_score.userid = u.id
AND sst_score.scormid = ss.scorm
AND sst_score.element = 'cmi.core.score.raw'
AND sst_score.scoid = ss.id
WHERE u.id IN([SOME_EXAMPLE_IDS_HERE]) AND u.deleted = 0
group by u.idnumber, c.id
Now the problem is that without the GROUP BY clause, some of the records have values for scorm_status, scorm_starttime etc. However, these contain duplicates. But, with the group by statement, only NULL values are returned for these columns. Does anyone have a clue on how to resolve this?
Using GROUP_CONCAT and SUBSTRING_INDEX:-
SELECT
u.idnumber AS user_idnumber,
SUBSTRING_INDEX(GROUP_CONCAT(sst_status.value), ',', 1) AS scorm_status,
SUBSTRING_INDEX(GROUP_CONCAT(sst_starttime.value), ',', 1) AS scorm_starttime,
SUBSTRING_INDEX(GROUP_CONCAT(sst_duration.value), ',', 1) AS scorm_duration,
SUBSTRING_INDEX(GROUP_CONCAT(sst_score.value), ',', 1) AS scorm_score,
u.id as uid,
s.id as scormid,
ss.id as ssid
FROM {user} u
LEFT JOIN {prog_user_assignment} prua ON prua.userid = u.id
LEFT JOIN {prog} pr ON prua.programid = pr.id
LEFT JOIN {prog_courseset} prcs ON prcs.programid = pr.id
LEFT JOIN {prog_courseset_course} prcsc ON prcsc.coursesetid = prcs.id
LEFT JOIN {course} c ON prcsc.courseid = c.id
LEFT JOIN {scorm} s ON s.id = cm.instance
LEFT JOIN {scorm_scoes} ss ON ss.scorm = s.id
LEFT JOIN {scorm_scoes_track} sst_status
ON sst_status.userid = u.id
AND sst_status.scormid = ss.scorm
AND sst_status.element = 'cmi_core.lesson_status'
AND sst_status.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_starttime
ON sst_starttime.userid = u.id
AND sst_starttime.scormid = ss.scorm
AND sst_starttime.element = 'x.start.time'
AND sst_starttime.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_duration
ON sst_duration.userid = u.id
AND sst_duration.scormid = ss.scorm
AND sst_duration.element = 'cmi.core.total_time'
AND sst_duration.scoid = ss.id
LEFT JOIN {scorm_scoes_track} sst_score
ON sst_score.userid = u.id
AND sst_score.scormid = ss.scorm
AND sst_score.element = 'cmi.core.score.raw'
AND sst_score.scoid = ss.id
WHERE u.id IN([SOME_EXAMPLE_IDS_HERE]) AND u.deleted = 0
group by u.idnumber, c.id
This is getting the first non null values of these fields. Note that this is relying on the fields not containing commas (but easy enough to specify a different separator for the GROUP_CONCAT). You can specify an order for the GROUP_CONCAT to get your preferred value if required.
Here is a very simplified version of your query:
select u.idnumber AS user_idnumber, sst_status.value AS scorm_status,
sst_starttime.value AS scorm_starttime, sst_duration.value AS scorm_duration,
sst_score.value AS scorm_score, u.id as uid, s.id as scormid, ss.id as ssid
. . .
group by u.idnumber, c.id;
You will notice that most of the columns in the select are not in the group by. This is using a (mis)feature of MySQL and would not generally be allowed in other databases.
What MySQL does is it chooses an abritrary value from one of the rows for the result. The idea is that this works nicely if the column is constant for the group. But, it doesn't usually work as expected in other circumstances.
If you want a non-NULL value, then you can use max() or min() to get the biggest or smallest value.
For instance:
min(sst_status.value) AS scorm_status
and so on.

Improve query performance from many Master table

I have a query. I have created index for all joined key, pre-filter the master table and choose specific rows to select, but it still take long time to show(sometimes it hangs). What should We do to improve the performance?
SELECT *
FROM t_responden a
INNER JOIN t_kepemilikan_tik b
ON a.res_id = b.res_id
INNER JOIN t_televisi c
ON a.res_id = c.res_id
INNER JOIN t_telepon_hp d
ON a.res_id = d.res_id
INNER JOIN t_radio e
ON a.res_id = e.res_id
INNER JOIN t_media_cetak f
ON a.res_id = f.res_id
INNER JOIN t_internet g
ON a.res_id = g.res_id
LEFT JOIN t_mst_pendidikan n
ON a.res_pendidikan_kk = n.kd_pendidikan
LEFT JOIN t_mst_pendidikan o
ON a.res_pendidikan = o.kd_pendidikan
LEFT JOIN t_mst_penghasilan p
ON a.res_penghasilan = p.kd_penghasilan
LEFT JOIN t_mst_aksesibilitas q
ON a.res_aksesibilitas = q.kd_akses
LEFT JOIN t_mst_mobilitas r
ON a.res_mobilitas = r.kd_mobilitas
LEFT JOIN t_mst_pekerjaan s
ON a.res_pekerjaan = s.kode
LEFT JOIN t_mst_pengeluaran t
ON a.res_pengeluaran = t.kode
INNER JOIN t_pernyataan h
ON a.res_id = h.res_id
INNER JOIN (SELECT * FROM t_mst_prop WHERE kode IN ( '3200', '1600', '1800', '3600' )) i
ON a.res_propinsi = i.kode
INNER JOIN (SELECT * FROM t_mst_kabkota WHERE kode_prop IN ( '3200', '1600', '1800', '3600' )) j
ON ( a.res_kabkota = j.kode
AND a.res_propinsi = j.kode_prop )
INNER JOIN (SELECT * FROM t_mst_kec WHERE kode_prop IN ( '3200', '1600', '1800', '3600' )) k
ON ( a.res_kecamatan = k.kode
AND a.res_kabkota = k.kode_kabkota
AND a.res_propinsi = k.kode_prop )
INNER JOIN (SELECT * FROM t_mst_desa WHERE kode_prop IN ( '3200', '1600', '1800', '3600' ))l
ON ( a.res_keldesa = l.kode
AND a.res_kabkota = l.kode_kabkota
AND a.res_propinsi = l.kode_prop
AND l.kode_kec = a.res_kecamatan )
WHERE a.res_tahunsurvei = 2013
AND res_propinsi IN ( '3200', '1600', '1800', '3600' )
ORDER BY 1
SELECT STRAIGHT_JOIN
*
FROM
t_responden a
INNER JOIN t_kepemilikan_tik b
ON a.res_id = b.res_id
INNER JOIN t_televisi c
ON a.res_id = c.res_id
INNER JOIN t_telepon_hp d
ON a.res_id = d.res_id
INNER JOIN t_radio e
ON a.res_id = e.res_id
INNER JOIN t_media_cetak f
ON a.res_id = f.res_id
INNER JOIN t_internet g
ON a.res_id = g.res_id
LEFT JOIN t_mst_pendidikan n
ON a.res_pendidikan_kk = n.kd_pendidikan
LEFT JOIN t_mst_pendidikan o
ON a.res_pendidikan = o.kd_pendidikan
LEFT JOIN t_mst_penghasilan p
ON a.res_penghasilan = p.kd_penghasilan
LEFT JOIN t_mst_aksesibilitas q
ON a.res_aksesibilitas = q.kd_akses
LEFT JOIN t_mst_mobilitas r
ON a.res_mobilitas = r.kd_mobilitas
LEFT JOIN t_mst_pekerjaan s
ON a.res_pekerjaan = s.kode
LEFT JOIN t_mst_pengeluaran t
ON a.res_pengeluaran = t.kode
INNER JOIN t_pernyataan h
ON a.res_id = h.res_id
INNER JOIN t_mst_prop i
ON a.res_propinsi = i.kode
INNER JOIN t_mst_kabkota j
ON a.res_propinsi = j.kode_prop
AND a.res_kabkota = j.kode
INNER JOIN t_mst_kec k
ON a.res_propinsi = k.kode_prop
AND a.res_kecamatan = k.kode
AND a.res_kabkota = k.kode_kabkota
INNER JOIN t_mst_desa l
ON a.res_propinsi = l.kode_prop
AND a.res_keldesa = l.kode
AND a.res_kabkota = l.kode_kabkota
AND a.res_kecamatan = l.kode_kec
WHERE
a.res_tahunsurvei = 2013
AND a.res_propinsi IN ( '3200', '1600', '1800', '3600' )
ORDER BY
1
You should have an index on your t_responden table ON ( res_tahunsurvei, res_propinsi) to match your where qualification criteria. Additionally, all your inner joins to the other tables where you are applying the IN via sub-selects is killing you. You are already limiting on the "kode"s in the where, so if you apply that as your join you should be good.
Additionally, since all the other tables appear to be more "lookup", I've added "STRAIGHT_JOIN" to tell MySQL to query in the order the tables you have listed