如何使用具有多个GROUP BY,子查询和WHERE IN的查询来优化查询?

时间:2014-12-01 13:24:19

标签: mysql sql join optimization query-optimization

我正在开发一个抓取项目,用于在不同的时间表上抓取项目及其分数。时间表是用户定义的时间段(日期),用于运行脚本。

表结构如下:

--
-- Table structure for table `test_join`
--

CREATE TABLE IF NOT EXISTS `test_join` (
  `schedule_id` int(11) NOT NULL,
  `player_name` varchar(50) NOT NULL,
  `type` enum('celebrity','sportsperson') NOT NULL,
  `score` int(11) NOT NULL,
  PRIMARY KEY (`schedule_id`,`player_name`,`type`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

--
-- Dumping data for table `test_join`
--

INSERT INTO `test_join` (`schedule_id`, `player_name`, `type`, `score`) VALUES
(1, 'sachin', 'sportsperson', 100),
(1, 'ganguly', 'sportsperson', 80),
(1, 'dravid', 'sportsperson', 60),
(1, 'sachin', 'celebrity', 100),
(2, 'sachin', 'sportsperson', 120),
(2, 'ganguly', 'sportsperson', 100),
(2, 'sachin', 'celebrity', 120);

刮擦是在一段时间内完成的,每个时间表预计会有大约10k +条目。时间表可以每天进行,因此数据将在5-6个月内增长到约200万。

在这些数据中,我需要执行查询以聚合在选定的时间表范围内遇到每个时间表的玩家。

例如:

我需要聚集相同的玩家,他们会遇到多个时间表。如果选择了计划1和2,则仅选择两个计划下的项目。

我使用以下查询根据类型

聚合结果

对于时间表1:

SELECT fullt.type,COUNT(*) as count,SUM(fullt.score) FROM
(SELECT tj.*
FROM `test_join` tj
RIGHT JOIN 
(SELECT `player_name`,`type`,COUNT(`schedule_id`) as c FROM `test_join` WHERE `schedule_id` IN (1,2) GROUP BY `player_name`,`type` HAVING c=2) stj 
on tj.player_name = stj.player_name 
WHERE tj.`schedule_id`=1
GROUP BY tj.`type`,tj.`player_name`)AS fullt
GROUP BY fullt.type

c = 2的原因;

WHERE `schedule_id` IN (1,2) GROUP BY `player_name`,`type` HAVING c=2 

这里我们选择两个时间表,1和2.然后,计数2用于使查询获取属于两个时间表的记录并发生两次。

它将生成如下结果,

附表1:预期结果

Schedule 1 :Expected Results

附表2:预期结果

Schedule 2 :Expected Results

这是我的预期结果,查询返回上面的结果。 (在实际情况下,我必须在相当大的MySQL表中工作)

根据我对标准化MySQL查询的理解,使用子查询,WHERE IN,varchar比较字段,多个GROUP BY会影响查询性能。 我需要实时和查询速度的聚合结果以及标准也是一个问题。如何在这种情况下优化以获得更好的性能。

编辑:

我现在减少了子查询:

SELECT fullt.type,COUNT(*) as count,SUM(fullt.score) FROM (
SELECT t.*
FROM `test_join` t 
INNER JOIN test_join t1 ON t.`player_name` = t1.player_name AND t1.schedule_id = 1
INNER JOIN test_join t2 ON t.player_name = t2.player_name AND t2.schedule_id = 2
WHERE t.schedule_id = 2 
GROUP BY t.`player_name`,t.`type`) AS fullt
GROUP BY fullt.type

这是一个更好的方法吗。我用JOINS替换了WHERE IN。

任何建议都将受到高度赞赏。如果需要,我很乐意提供任何支持信息。

1 个答案:

答案 0 :(得分:0)

在MYSQL中尝试以下SQL查询:



SELECT tj.`type`,COUNT(*) as count,SUM(tj.`score`) FROM
`test_join` tj
where tj.`schedule_id`=1 
and `player_name` in 
(
select tj1.`player_name` from `test_join` tj1 
group by tj1.`player_name` having count(tj1.`player_name`) > 1  
)
group by tj.`type`




实际上我在Sybase中尝试了相同的数据,因为我的机器上没有安装MySQL。它的工作正如预期的那样!



CREATE TABLE #test_join
 (
  schedule_id int NOT NULL,
  player_name varchar(50) NOT NULL,
  type1 varchar(15) NOT NULL,
  score int NOT NULL,
 ) 

INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES
(1, 'sachin', 'sportsperson', 100)



INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(1, 'ganguly', 'sportsperson', 80)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(1, 'dravid', 'sportsperson', 60)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(1, 'sachin', 'celebrity', 100)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(2, 'sachin', 'sportsperson', 120)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(2, 'ganguly', 'sportsperson', 100)
INSERT INTO #test_join (schedule_id, player_name, type1, score) VALUES(2, 'sachin', 'celebrity', 120)

select * from #test_join


Print 'Solution #1 : Inner join'

select type1,count(*),sum(score) from 
#test_join
where schedule_id=1 and player_name in (select player_name from #test_join t1 group by player_name having count(player_name) > 1  )
group by type1



select player_name,type1,sum(score) Score into #test_join_temp 
from #test_join 
group by player_name,type1
having count(player_name) > 1

Print 'Solution #2 using Temp Table'
--select * from #test_join_temp 
select type1,count(*),sum(score) from 
#test_join
where schedule_id=1 and player_name in (select player_name from #test_join_temp )
group by type1




我希望这有助于:)