请检查我的MYSQL查询并给我建议?

请检查我的MYSQL查询并给我建议?,mysql,Mysql,这是我的mysql查询 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

这是我的mysql查询

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 
请检查我的子查询

(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
这是我的子查询

(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
当我执行查询时,服务器需要很长时间才能执行。那么,如何简化? 请告诉我


谢谢。

重要的是要知道,如果没有索引,像“XXXX%”这样的操作非常慢。在某些情况下,这可能需要很长时间。此外,您正在执行四个子选择,而不是连接,这同样会更慢。下面我添加了一个完整的查询,它将产生相同的结果。另一种方法是通过减少联接的数量来减少查询的大小,并使用规范化的输出。也就是说,对于每一个nric和名称,你将有多行,而不是每一类的re_标记英语、数学、2008、2009等,你将有两列,其中包含代码FEEN或FEMA和标记

尝试一下以下查询,看看它是否更适合您:

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
编辑:包括规范化版本:

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
这将产生如下行:

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

请注意,这四条记录的唯一更改值是code、mark和year。您将获得比以前多4倍的记录,但它的运行速度也应该比以前快很多。您的代码必须迭代所有行并根据需要聚合它们。

请尝试以下操作:

  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    
如果需要,用左连接替换内部连接

如果此解决方案仍然不够,还有两个选项:

对每个条件使用视图1

将视图FEEN2008创建为 选择重新标记、重新标记 来自si_的结果为re 其中re.re_代码类似“FEEN%” 而re.re_year='2008' 和re.re_学期='2'

并将原始查询替换为以下内容:

 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
数据库引擎通常会优化视图,而且可能会更快。不过,我不知道MySql是如何与它们协同工作的

使用以下字段在si_结果中创建索引:re_代码、re_年份、re_学期和re_nric 注意这会使插入和更新速度变慢


这样的子查询在我看来总是可疑的。研究获取这些数据的其他方法是很有诱惑力的……也许是将其留在桌面上?si_results表被使用了3次,这对我来说是一个很好的重写为左连接的候选者。尽管如此,由于只有3000行,它真的不应该造成太多的慢


相反,删除子查询并再次检查性能。也许你真正需要的只是一个新的索引

在2009年和2008年数学考试之前,您的查询中似乎缺少了两个AS的实例。好的,我同意。但这是可选的。对吗?嗨,乔纳森,你知道如何在我的问题中附加图像文件吗?谢谢你的回复,我正在努力。请稍等。谢谢你的帮助。我明白你的疑问。我得到了预期行类型和字段。但是要花很长时间。你能看到马特先生的答案吗?马特的问题很好。但我需要所有字段都放在一行中。你能改变/修改马特先生的问题吗?请帮我看一下。感谢MattAs先生的恶意版本,这个查询和我答案中的第一个查询是一样的。名称IC ENGLISH_2008 ENGLISH_2009 Mathematics_2008 Mathematics_2009 ISC_GPA xxx 120 40 50 55 2.25我需要这样的报告名称IC ENGLISH_2008 ENGLISH_2009 Mathematics_2008 Mathematics_2009 ISC_GPA xxx 120 40 50 55 2.25我需要结果是这样的。我喜欢你的询问。非常快。请告知我,我的第一个较长的查询是否不生成您要查找的数据?由于所有的连接和对文本列的过滤,查询将需要一段时间。查看索引以确保所有联接列都具有良好的索引方案。从谷歌搜索“mysql中的列索引”开始,你应该有足够的阅读量来持续很长时间。谢谢马特先生,你的建议对我很好。谢谢我需要阅读如何设置索引。