我正在寻找一种方法来容纳有多个结果来找到最大值和最小值。我找到了上一个问题的链接: 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
答案 0 :(得分: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,我发现它并不是你想要的。如果你想找到所有相应的行,你最好像戈登建议的那样行事。
虽然我找到了解决此问题的另一种方法,但它可能只比使用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;
我也有变量变体(类似于戈登的变量)。所以你可以选择这些选项。
答案 1 :(得分: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);