两个看似相同的查询在使用count(分页)时返回不同的结果

时间:2012-07-01 04:31:47

标签: php mysql sql

出于分页原因,我正在向我的数据库运行两个查询。因此,每个查询几乎相同。我的COUNT(*)查询未返回非计数查询的结果数。我很困惑为什么会这样。查询如下。

SELECT p.host_id, p.rating_support, p.rating_tech, MAX(p.rating_overall) AS rating_overall, p.publish_rating, h.name, prices.price, prices.term_duration
FROM plans p
INNER JOIN hosts AS h ON h.id = p.host_id
INNER JOIN (SELECT plan_id, price, term_duration FROM prices WHERE price > 0 AND price < 50 AND term_duration = 1) prices ON prices.plan_id = p.id
WHERE p.published = 1 AND h.published = 1
GROUP BY p.host_id
ORDER BY rating_overall desc LIMIT 0, 12

SELECT COUNT(*) AS count
FROM plans p
INNER JOIN hosts AS h ON h.id = p.host_id
INNER JOIN (SELECT plan_id, price, term_duration FROM prices WHERE price > 0 AND price < 50 AND term_duration = 1) prices ON prices.plan_id = p.id
WHERE p.published = 1 AND h.published = 1
GROUP BY p.host_id

我不是MySQL的专家。除了计数未提供正确数量的结果外,非计数查询也能正常工作。

对这个问题的任何启示都会很棒。

2 个答案:

答案 0 :(得分:4)

借助Dems的评论(hunt down and upvote him某处:),我创建了这个查询。请注意,我删除了子查询,因为它似乎没必要:

SELECT
  COUNT( DISTINCT p.host_id )
FROM       plans p
INNER JOIN hosts h ON h.id = p.host_id
INNER JOIN prices  ON prices.plan_id = p.id
                  AND prices.price > 0
                  AND prices.price < 50
                  AND prices.term_duration = 1
WHERE p.published = 1
  AND h.published = 1

我原来的回答:

要获取总行数,您必须将GROUP BY查询包装到外部SELECT

SELECT COUNT(*)
FROM (
  SELECT NULL -- we are just counting, so we need no actual data -> a bit faster
  FROM       plans p
  INNER JOIN hosts h ON h.id = p.host_id
  INNER JOIN prices  ON prices.plan_id = p.id
                    AND prices.price > 0
                    AND prices.price < 50
                    AND prices.term_duration = 1
  WHERE p.published = 1
    AND h.published = 1
  GROUP BY p.host_id
) AS all_rows_without_data

或者您可以使用SQL_CALC_FOUND_ROWS + FOUND_ROWS()

http://dev.mysql.com/doc/refman/5.0/en/information-functions.html#function_found-rows

  

SELECT语句可能包含LIMIT子句以限制该数字   服务器返回到客户端的行数。在某些情况下,它是   希望知道该语句将返回多少行   没有LIMIT,但没有再次运行语句。获得   此行计数,在SELECT中包含SQL_CALC_FOUND_ROWS选项   声明,然后调用FOUND_ROWS():

首先,只需选择所需的行,但添加SQL_CALC_FOUND_ROWS

SELECT SQL_CALC_FOUND_ROWS
  p.host_id, p.rating_support, p.rating_tech,
  MAX(p.rating_overall) AS rating_overall,
  p.publish_rating, h.name, prices.price, prices.term_duration
FROM       plans p
INNER JOIN hosts AS h ON h.id = p.host_id
INNER JOIN prices  ON prices.plan_id = p.id
                  AND prices.price > 0
                  AND prices.price < 50
                  AND prices.term_duration = 1
WHERE p.published = 1 AND h.published = 1
GROUP BY p.host_id
ORDER BY rating_overall desc
LIMIT 0, 12;

其次,如果第一个查询中没有LIMIT语句,则获取将返回的行数:

SELECT FOUND_ROWS();

更新SQL_CALC_FOUND_ROWS + FOUND_ROWS()似乎不太可靠,因为未知原因(不只是我:FOUND_ROWS() keeps returning 0)总是回零:

http://sqlfiddle.com/#!2/7304d/8

答案 1 :(得分:1)

第二次查询的结果将返回相同的行数,但第一行不会返回总数。

结果将给出每行每组的计数:

3
5
1
6
etc.
etc.

要将结果放到一行,请在完整结果集中使用PHP中的COUNT(DISTINCT p.host_id)array_sum()