优化复杂的SQL查询

时间:2011-09-14 20:44:43

标签: mysql optimization query-optimization

我确信有更好的方法可以做到这一点。它查看applications表并收集每个作业的特定状态的所有应用程序。

所以它看起来像这样:

pending | screened | interviewed | accepted | offer | hired | job title
0         0          0             0          0       2       dirt mover
2         0          1             1          0       1       tree planter
7         2          1             1          1       3       hole digger

这是sql(为了便于阅读,删除了额外的联合列,如果你可以调用这个查询可读)

select sum(pending) as pending, sum(screened) as screened, sum(interviewed) 
as interviewed, sum(accepted) as accepted, sum(offer) as offer, sum(hired) 
as hired, sum(declined) as declined, sum(rejected) as rejected, title, jobid
 from 
(

(select count(j.job_id) as pending, j.title as title, j.job_id as jobid from 
applications a, jobs j where j.job_id = a.job_id and status = 'Pending' group by 
j.job_id)

union

(select count(j.job_id) as screened, j.title as title, j.job_id as jobid from 
applications a, jobs j where j.job_id = a.job_id and status = 'Screened' group by 
j.job_id)

union

(select count(j.job_id) as interviewed, j.title as title, j.job_id as jobid from 
applications a, jobs j where j.job_id = a.job_id and status = 'Interviewed' group by 
j.job_id)

union

(select count(j.job_id) as accepted, j.title as title, j.job_id as jobid from 
applications a, jobs j where j.job_id = a.job_id and status = 'Accepted' group by 
j.job_id)

union

(select count(j.job_id) as offer, j.title as title, j.job_id as jobid from 
applications a, jobs j where j.job_id = a.job_id and status = 'Offer Made' group by 
j.job_id)

union

(select count(j.job_id) as hired, j.title as title, j.job_id as jobid from 
applications a, jobs j where j.job_id = a.job_id and status = 'Offer Accepted' group
 by j.job_id)

union

(select count(j.job_id) as declined, j.title as title, j.job_id as jobid from 
applications a, jobs j where j.job_id = a.job_id and status = 'Offer Declined' group
 by j.job_id)

union

(select count(j.job_id) as rejected, j.title as title, j.job_id as jobid from 
applications a, jobs j where j.job_id = a.job_id and status = 'Rejected' group by 
j.job_id)

) as summ group by title order by title

这是SHOW CREATE TABLE应用程序

CREATE TABLE IF NOT EXISTS `applications` (
  `app_id` int(5) NOT NULL auto_increment,
  `job_id` int(5) NOT NULL,
  `status` varchar(25) NOT NULL,
  `reviewed` datetime NOT NULL,
  PRIMARY KEY  (`app_id`),
  UNIQUE KEY `app_id` (`app_id`),
  KEY `job_id` (`job_id`),
  KEY `status` (`status`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2720 ;

这是SHOW CREATE TABLE作业

CREATE TABLE IF NOT EXISTS `jobs` (
  `job_id` int(5) NOT NULL auto_increment,
  `title` varchar(25) NOT NULL,
  PRIMARY KEY  (`app_id`),
  KEY `job_id` (`job_id`),
) ENGINE=MyISAM  DEFAULT CHARSET=latin1;

2 个答案:

答案 0 :(得分:2)

看起来您正在进行PIVOT /交叉表查询。这样的事情可以解决问题。

SELECT COUNT(CASE
               WHEN status = 'Pending' THEN 1
             END) AS pending,
       COUNT(CASE
               WHEN status = 'Screened' THEN 1
             END) AS screened,
       /*Remaining ones left as an exercise for the reader*/
       title
FROM   applications a
       JOIN jobs j
         ON j.job_id = a.job_id
GROUP  BY title
ORDER  BY title  

答案 1 :(得分:0)

首先,需要注意一些事项:

  1. 不要使用交叉连接(Theta连接)。这确实会减慢您的查询速度:

    SELECT * FROM table_1,table_2 WHERE table_1.id = table_2.t1_id

  2. 改为使用:

    SELECT * FROM table_1 INNER JOIN table_2 ON(table_1.id = table_2.t1_id)
    
    1. PRIMARY KEYs已经是UNIQUE KEYS
    2. 现在,我的方式就是这样:

      SELECT
          SUM(a.app_id),
          a.status
      FROM
          applications a INNER JOIN   
          jobs j ON (j.job_id=a.job_id)
      GROUP BY
          j.job_id,
          a.status
      

      对于这个简单的查询,你应该得到类似的东西:

      JOB_TITLE    | STATUS        |   COUNT
      dirt mover   | pending       |    0
      dirt mover   | screened      |    0
      dirt mover   | interviewed   |    0
      dirt mover   | accepted      |    0
      dirt mover   | offer         |    0
      dirt mover   | hired         |    2
      
      tree planter | pending       |    2
      tree planter | screened      |    0
      tree planter | interviewed   |    1
      tree planter | accepted      |    1
      tree planter | offer         |    0
      tree planter | hired         |    1
      ...
      

      请注意,标题会重复,但这不是问题,因为您可以获得相同的信息。查询将快几倍,而且更简单。