3

ページネーションの理由で、データベースに対して2つのクエリを実行しています。そのため、各クエリはほぼ同じです。私の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の専門家ではありません。カウントが正しい数の結果を提供しないことに加えて、非カウントクエリは完全に機能します。

この問題についての光は素晴らしいでしょう。

4

2 に答える 2

4

デムズのコメント(どこかで彼を追い詰めて賛成する:)の助けを借りて、私はこのクエリを作成しました。サブクエリは不要と思われるため、削除したことに注意してください。

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()は0を返し続けます):

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

于 2012-07-01T08:17:31.850 に答える