如何改进此查询?

时间:2009-09-01 09:21:29

标签: mysql

我有一张桌子,

| PAGELETS | CREATE TABLE `PAGELETS` (
  `page_key` int(32) unsigned NOT NULL,
  `pagelet_serial` int(32) unsigned NOT NULL,
  `pagelet_shingle` int(32) unsigned NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 

我想:

1) Find all the pagelet_shingles where quantity > 1 ( occurs more than once)
2) out of these only output those that have different page_key

这是产生半正确答案的查询:

SELECT * FROM PAGELETS WHERE pagelet_shingle IN( SELECT pagelet_shingle FROM PAGELETS GROUP BY pagelet_shingle HAVING COUNT(DISTINCT page_key) > 1) ORDER BY pagelet_shingle;

不幸的是,在一个小数据集上大约需要18秒;

我有另一个查询,

SELECT dt1.* FROM 
(SELECT * FROM PAGELETS 
GROUP BY page_key, pagelet_shingle HAVING COUNT(*) = 1) 
dt1 JOIN 
(SELECT * FROM PAGELETS GROUP BY pagelet_shingle HAVING COUNT(*) > 1) 
dt2 USING (pagelet_shingle) ORDER BY pagelet_shingle

由技术上不正确的专家给出(与你有关的事情不能SELECT * .. GROUP)但是会产生更快的结果,其中

SELECT * FROM PAGELETS WHERE pagelet_shingle = 57

+----------+----------------+-----------------+
| page_key | pagelet_serial | pagelet_shingle |
+----------+----------------+-----------------+
|        1 |             99 |              57 | 
|        1 |             99 |              57 | 
|        2 |            228 |              57 | 
|        2 |            228 |              57 | 
+----------+----------------+-----------------+

半正确的查询产生

+----------+----------------+-----------------+
| page_key | pagelet_serial | pagelet_shingle |
+----------+----------------+-----------------+
|        1 |             99 |              57 | 
|        1 |             99 |              57 | 
|        2 |            228 |              57 | 
|        2 |            228 |              57 | 
+----------+----------------+-----------------+ 

虽然不正确的查询在其结果集中没有pagelet_shingle = 57

我想要的结果是

+----------+----------------+-----------------+
| page_key | pagelet_serial | pagelet_shingle |
+----------+----------------+-----------------+
|        1 |             99 |              57 |  
|        2 |            228 |              57 | 
+----------+----------------+-----------------+ 

每次只发生一次。

将省略在同一pagelet_serial中出现两次的pagelet_shingle。

所以我想问下列内容: 1)有没有办法加快csemi或正确的查询,以达到不正确的速度 2)或者有没有办法解决不正确的问题以产生正确的结果(我不关心严格性)

6 个答案:

答案 0 :(得分:0)

SELECT DISTINCT p.* ...之类的声音将是您的选择。

P.S。我真的推荐第二个!让一切变得缓慢(就像你刚才注意到的那样),并且只应在必要时使用。

答案 1 :(得分:0)

此查询不能解决您的问题吗?

SELECT dt1.* FROM 
(SELECT DISTINCT * FROM PAGELETS 
GROUP BY page_key, pagelet_shingle HAVING COUNT(*) = 1) 
dt1 JOIN 
(SELECT * FROM PAGELETS GROUP BY pagelet_shingle HAVING COUNT(*) > 1) 
dt2 USING (pagelet_shingle) GROUP BY pagelet_shingle

答案 2 :(得分:0)

什么是

SELECT * FROM PAGELETS GROUP BY pagelet_serial, pagelet_shingle HAVING COUNT(*) > 0

给你?

答案 3 :(得分:0)

使用GROUP BY和HAVING,例如

  SELECT *
    FROM `pagelets`
GROUP BY `pagelet_shingle`
  HAVING COUNT(*) > 1

另外你可以做一个自连接来输出所有列,不过在mysql中它应该以那种方式工作(与SQL标准不同)

答案 4 :(得分:0)

从我读到的内容来看,你在寻找的是:

SELECT DISTINCT p1.page_key, p1.pagelet_serial, p1.pagelet_shingle
  FROM PAGELETS p1
  JOIN PAGELETS p2 ON p2.page_key         = p1.page_key
                  AND p2.pagelet_serial   = p1.pagelet_serial
                  AND p2.pagelet_shingle <> p1.pagelet_shingle

该查询将充分利用(page_key, pagelet_serial)上的索引,并且应该在十分之一秒内完成,而不是几秒钟。

如果这不是您想要的,请告诉我们如果您的表中的值是:(1,2,3),(1,2,3),(1,1),您会得到什么结果,3),(1,1,3),(1,2,4),(1,2,4),(1,1,4-),(1,1,4-)

答案 5 :(得分:0)

您是否尝试过使用exists代替in

检查一下: http://decipherinfosys.wordpress.com/2007/01/30/in-vs-exists/

希望这有帮助