0

我正在寻找一种方法来适应有多个结果来找到最大值和最小值。我找到了上一个问题的链接: max Counts

给出的答案之一是:

SELECT  color_id, COUNT(color_id) totalCount
FROM    products 
WHERE   item_id = 1234 
GROUP   BY color_id 
HAVING  COUNT(color_id) =
(
  SELECT  COUNT(color_id) totalCount
  FROM    products 
  WHERE   item_id = 1234 
  GROUP   BY color_id 
  ORDER BY totalCount DESC
  LIMIT 1  
)

这种公认的做法尤其适用于大型数据库吗?如果有意义的话,上面的查询不是基本上在自身内部运行吗?

我有一个更复杂的查询,还需要找到 ma 和 min。我想优化它:

编辑

SELECT `system_users`.`first`, `system_users`.`last`,  COUNT(`quotes`.`created_by`) as most_quotes
FROM `quotes` 
INNER JOIN `system_users`
ON `quotes`.`created_by` = `system_users`.`id`
where `system_users`.`store_id` = '$createdID' 
and `quotes`.`date_created` between '$startDate' and '$endDate' group by(`created_by`)
HAVING count(`quotes`.`created_by`) = 
(
SELECT COUNT(`quotes`.`created_by`)
FROM `quotes` 
INNER JOIN `system_users`
ON `quotes`.`created_by` = `system_users`.`id`
where `system_users`.`store_id` = '$createdID' 
and `quotes`.`date_created` between '$startDate' and '$endDate' group by(`created_by`) ORDER BY count(`created_by`) DESC limit 1
)
OR
(
SELECT COUNT(`quotes`.`created_by`)
FROM `quotes` 
INNER JOIN `system_users`
ON `quotes`.`created_by` = `system_users`.`id`
where `system_users`.`store_id` = '$createdID'
and `quotes`.`date_created` between '$startDate' and '$endDate' group by(`created_by`) ORDER BY count(`created_by`) ASC limit 1
)
ORDER BY most_quotes ASC

到目前为止,我正在尝试寻找不同的方法来找到最大值和最小值。对此的任何更多帮助将不胜感激谢谢mc

4

2 回答 2

1

这是一个坏主意 - 在大型数据库上使用 HAVING。而且,此外,您的问题可以通过这种方式解决(我有 MySQL 5.5 版本):

SELECT  
  color_id, 
  COUNT(color_id) AS totalCount
FROM    
  products 
WHERE   
  item_id = 1234 
GROUP BY 
  color_id 
ORDER BY 
  totalCount DESC 
LIMIT 1

问题HAVING在于它是在整个查询完成后执行的,即存储引擎已经工作,因此无法针对HAVING条件进行索引或其他优化 - 因此,它可以被视为完整的结果集扫描。

感谢@GordonLinoff,我发现这并不是您想要的。如果您试图找到所有相应的行,您最好像 Gordon 建议的那样行事。

虽然我找到了另一种解决这个问题的方法,但它可能只比原始变体好几个HAVING(而且 - 更好,因为存储引擎两次都会涉及)

SELECT
  first.color_id, 
  first.rows_count 
FROM 
  (SELECT color_id, COUNT(1) AS rows_count FROM products WHERE item_id=1234 GROUP BY color_id) AS first 
  LEFT JOIN
  (SELECT color_id, COUNT(1) AS rows_count FROM products WHERE item_id=1234 GROUP BY color_id ORDER BY rows_count DESC LIMIT 1) AS second 
    ON first.rows_count=second.rows_count 
WHERE second.rows_count IS NOT NULL;

我也有变量的变体(类似于戈登的变体)。因此,您可以在这些选项之间进行选择。

于 2013-08-20T12:48:42.553 回答
0

您的问题的答案是,在 MySQL 中有多种方法可以使用一个查询来解决这个问题。

一种方法是您问题中的方法。另一个是使用变量:

select color_id, totalcount
from (SELECT color_id, COUNT(color_id) as totalCount,
             @maxcount = if(@maxcount < count(color_id), count(color_id), @maxcount)
      FROM products cross join
           (select @maxcount := 0) const
     WHERE item_id = 1234 
     GROUP BY color_id 
    ) t
where totalCount = @maxcount;

我不太喜欢在 MySQL 中使用变量,但通常它们是有效表达查询的唯一方法。我相信这是将您想要的内容编写为单个查询的最有效方法。

第三种方法是使用临时表。第四种方法是将having条件中的子查询移动到另一个连接。

在大多数其他数据库中,您只需使用窗口函数。就像是:

select color_id, totalcount
from (SELECT color_id, COUNT(color_id) as totalCount,
             max(count(color_id)) over () as maxTotalCount
      FROM products
     WHERE item_id = 1234 
     GROUP BY color_id 
    ) t
where totalCount = maxTotalCount;

但是,MySQL 不支持这些。

编辑:

如果您想要使用变量的最大值和最小值:

select color_id, totalcount
from (SELECT color_id, COUNT(color_id) as totalCount,
             @maxcount = if(@maxcount < count(color_id), count(color_id), @maxcount),
             @mincount = if(@mincount > count(color_id) or @mincount = -1, count(color_id), @mincount)
      FROM products cross join
           (select @maxcount := -1, @mincount := -1) const
     WHERE item_id = 1234 
     GROUP BY color_id 
    ) t
where totalCount in (@mincount, @maxcount);
于 2013-08-20T13:33:03.980 回答