【问题标题】:mysql Max having multiple instancesmysql Max有多个实例
【发布时间】:2013-08-20 12:41:38
【问题描述】:

我正在寻找一种方法来容纳多个结果来找到最大值和最小值。我发现此链接指向上一个问题: 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

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

【问题讨论】:

    标签: mysql count max having


    【解决方案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;
    

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

    【讨论】:

    • 这可能是一个更有效的查询,但它不能回答问题。该问题明确指出,多个“color_id”可能满足最大条件。这只会返回一个值。
    • 嗯.. @GordonLinoff,你是对的 - 因为上面的查询将只返回一行。我会纠正的。
    • 感谢您的回复。尽管我的查询比这要复杂一些。就目前而言,这就是我所拥有的,用于找到最大值和最小值:
    • 请查看我上面的编辑,我无法将我的查询添加为评论。我想容纳超过一个最大值和最小值,但不知道如何
    • @GordonLinoff 您能否为我的附加报价建议一个解决方案,以找到最大值和最小值?谢谢
    【解决方案2】:

    您的问题的答案是,在 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);
    

    【讨论】:

    • 您能建议解决我上面编辑过的查询吗?谢谢
    • 我运行了这个查询,它返回了空列
    猜你喜欢
    • 2016-08-25
    • 1970-01-01
    • 2021-02-06
    • 2012-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 1970-01-01
    相关资源
    最近更新 更多