开发者

please check my MYSQL query & give me advice?

this is my mysql query.

SELECT s.s_nric                           AS nric,
       s.s_name                           AS name,
       s.s_psle_eng                       AS psle_eng,
       s.s_psle_math                      AS psle_maths,
       s.s_psle_aggr                      AS psle_aggr,
       (SELECT re.re_mark
        FROM   si_results re
        WHERE  re.re_code LIKE 'FEEN%'
               AND re.re_year = '2008'
               AND re.re_semester = '2'
               AND re.re_nric = s.s_nric) AS english_2008,
       (SELECT re.re_mark
        FROM   si_results re
        WHERE  re.re_code LIKE 'FEMA%'
               AND re.re_year = '2008'
               AND re.re_semester = '2'
               AND re.re_nric = s.s_nric) maths_2008,
       (SELECT re.re_mark
        FROM   si_results re
        WHERE  re.re_code LIKE 'FEEN%'
               AND re.re_year = '2009'
               AND re.re_semester = '2'
               AND re.re_nric = s.s_nric) AS english_2009,
       (SELECT re.re_mark
        FROM   si_results re
        WHERE  re.re_code LIKE 'FEMA%'
               AND re.re_year = '2009'
               AND re.re_semester = '2'
               AND re.re_nric = s.s_nric) maths_2009,
       isc.isc_g_gpa                      AS isc_gpa
FROM   si_student_data AS s
       LEFT JOIN si_isc_gpa AS isc
         ON isc.isc_g_nric = s.s_nric
WHERE  1 = 1
       AND s.s_admission_year = '2008'
GROUP  BY s.s_nric
ORDER  BY s.s_gender,
          s.s_name ASC 

please check my sub query

this is my sub query

(SELECT re.re_mark 
  FROM si_resu开发者_C百科lts re 
  WHERE re.re_code like 'FEEN%' 
    AND re.re_year='2008' 
    AND re.re_semester='2' 
    AND re.re_nric=s.s_nric) as English_2008, 
(SELECT re.re_mark 
  FROM si_results re 
  WHERE re.re_code like 'FEMA%' 
    AND re.re_year='2008' 
    AND re.re_semester='2' 
    AND re.re_nric=s.s_nric) Maths_2008, 
(SELECT re.re_mark 
  FROM si_results re 
  WHERE re.re_code like 'FEEN%' 
    AND re.re_year='2009' 
    AND re.re_semester='2' 
    AND re.re_nric=s.s_nric ) as English_2009, 
(SELECT re.re_mark 
  FROM si_results re 
  WHERE re.re_code like 'FEMA%' 
    AND re.re_year='2009' 
    AND re.re_semester='2' 
    AND re.re_nric=s.s_nric ) Maths_2009

When I execute my query, server take long time to execute. So how to make simple? please advice me.

Thanks.


It's important to know that doing a LIKE 'XXXX%' is very slow if it's not indexed. This can take forever in some cases. Also, you're doing four sub selects rather than joins which is again slower. Below I've added a full query which will produce the same results. The alternative to this is to reduce the size of the query by reducing the number of joins and instead have a NORMALIZED output. That is for every nric and name you'll have multiple rows with instead of re_mark for every type of class (english, maths, 2008, 2009, etc) you'll have two columns which contain the code (FEEN or FEMA) and the mark.

Give the following query a try and see if it works any better for you:

SELECT s.s_nric                           AS nric,
       s.s_name                           AS name,
       s.s_psle_eng                       AS psle_eng,
       s.s_psle_math                      AS psle_maths,
       s.s_psle_aggr                      AS psle_aggr,
       e_2008_feen.re_mark                AS english_2008,
       e_2008_fema.re_mark                AS maths_2008,
       e_2009_feen.re_mark                AS english_2009,
       e_2009_fema.re_mark                AS maths_2009,
       isc.isc_g_gpa                      AS isc_gpa
FROM   si_student_data AS s
INNER JOIN si_results e_2008_feen
    ON e_2008_feen.re_code LIKE 'FEEN%'
       AND e_2008_feen.re_year = '2008'
       AND e_2008_feen.re_semester = '2'
       AND e_2008_feen.re_nric = s.s_nric

INNER JOIN si_results e_2008_fema
    ON e_2008_fema.re_code LIKE 'FEMA%'
       AND e_2008_fema.re_year = '2008'
       AND e_2008_fema.re_semester = '2'
       AND e_2008_fema.re_nric = s.s_nric

INNER JOIN si_results e_2009_feen
    ON e_2009_feen.re_code LIKE 'FEEN%'
       AND e_2009_feen.re_year = '2009'
       AND e_2009_feen.re_semester = '2'
       AND e_2009_feen.re_nric = s.s_nric

INNER JOIN si_results e_2009_fema
    ON e_2009_fema.re_code LIKE 'FEMA%'
       AND e_2009_fema.re_year = '2009'
       AND e_2009_fema.re_semester = '2'
       AND e_2009_fema.re_nric = s.s_nric

LEFT JOIN si_isc_gpa AS isc
    ON isc.isc_g_nric = s.s_nric

WHERE  s.s_admission_year = '2008'
GROUP  BY s.s_nric
ORDER  BY s.s_gender,
          s.s_name ASC

Edit: Included a normalized version:

SELECT s.s_nric                           AS nric,
       s.s_name                           AS name,
       s.s_psle_eng                       AS psle_eng,
       s.s_psle_math                      AS psle_maths,
       s.s_psle_aggr                      AS psle_aggr,
       si_results.re_code                 AS code
       si_results.re_mark                 AS mark
       si_results.re_year                 AS year
       isc.isc_g_gpa                      AS isc_gpa

FROM   si_student_data AS s

INNER JOIN si_results e_2008_feen
    ON si_results.re_nric = s.s_nric

LEFT JOIN si_isc_gpa AS isc
    ON isc.isc_g_nric = s.s_nric

WHERE  s.s_admission_year = '2008'
    AND si_results.re_year in ('2008', '2009')
    AND si_results.re_semester = '2'
    AND (
          si_results.re_code LIKE 'FEEN%'
          OR si_results.re_code LIKE 'FEMA%'
     )

GROUP  BY s.s_nric
ORDER  BY s.s_gender,
          s.s_name ASC

This will produce rows like:

nric: 1
name: 'student 1'
psle_eng: eng1
psle_maths: maths1
psle_aggr: aggr1
code: FEENXXXX
mark: 5
year: 2008
isc_gpa: gpa1



nric: 1
name: 'student 1'
psle_eng: eng1
psle_maths: maths1
psle_aggr: aggr1
code: FEENXXXX
mark: 3
year: 2009
isc_gpa: gpa1


nric: 1
name: 'student 1'
psle_eng: eng1
psle_maths: maths1
psle_aggr: aggr1
code: FEMAXXXX
mark: 4.5
year: 2008
isc_gpa: gpa1


nric: 1
name: 'student 1'
psle_eng: eng1
psle_maths: maths1
psle_aggr: aggr1
code: FEMAXXXX
mark: 5
year: 2009
isc_gpa: gpa1

Notice that the only values changing for the four records is code, mark, and year. You'll get 4 times the number of records back as before but it should run significantly faster than before as well. Your code will have to iterate all the rows and aggregate them as needed.


Try something like this:

  re1.re_mark AS english_2008,
  re2.re_mark AS maths_2008,
  re3.re_mark AS english_2009,
  re4.re_mark AS maths_2009,
  isc.isc_g_gpa AS isc_gpa

FROM   si_student_data AS s
  INNER JOIN si_results as re1 ON re1.re_code LIKE 'FEEN%' AND re1.re_year = '2008' 
            AND re1.re_semester = '2' AND re1.re_nric = s.s_nric
  INNER JOIN si_results as re2 ON re2.re_code LIKE 'FEMA%' AND re2.re_year = '2008' 
            AND re2.re_semester = '2' AND re2.re_nric = s.s_nric
  INNER JOIN si_results as re3 ON re3.re_code LIKE 'FEEN%' AND re3.re_year = '2009' 
            AND re3.re_semester = '2' AND re3.re_nric = s.s_nric
  INNER JOIN si_results as re4 ON re4.re_code LIKE 'FEMA%' AND re4.re_year = '2009' 
            AND re4.re_semester = '2' AND re4.re_nric = s.s_nric    

Replace INNER JOIN with LEFT JOIN if needed

If this solution is still not enough two more options:

  • Use Views (1 for each condition you have)

    CREATE VIEW FEEN2008 AS SELECT re_mark, re_nric FROM si_results as re WHERE re.re_code LIKE 'FEEN%' AND re.re_year = '2008' AND re.re_semester = '2'

    and replace original query with something like:

     FROM   si_student_data AS s
        INNER JOIN FEEN2008 as re1 ON re1.re_nric = s.s_nric
        INNER JOIN FEMA2008 as re2 ON re2.re_nric = s.s_nric
        INNER JOIN FEEN2009 as re3 ON re3.re_nric = s.s_nric      
        INNER JOIN FEMA2009 as re4 ON re4.re_nric = s.s_nric
    

    Database engines usually optimize views and it may be faster. Not sure how MySql work with them though.

  • Create an index in si_results using fields: re_code, re_year, re_semester and re_nric Beware this will make inserts and updates slower.


sub queries like that always look suspicious to me. It is very tempting to examine other ways to get that data...perhaps left joining on the table? the si_results table is used 3 times and kind of raises a red flag to me as a good candidate to rewrite into a left join. That said though, with only 3000 rows, it really shouldn't be causing much slowness.

Instead, remove the subqueries and check the performance again. Perhaps all you really need is a new index.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜