0

私は次の問題に対するエレガントな解決策を探しています:

現在、ページ番号制限付きのORDERBY日付のエントリを一覧表示するページがあります。これが私のコードの抜粋です:

<?php
$intPageNumber = 1;
if ( isset($this->GET['p']) && (integer)$this->GET['p'] > 1 ) $intPageNumber = (integer)$this->GET['p'];
$strLimit = " LIMIT " . (($intPageNumber-1)*$intItemsPerPage) . ", " . $intItemsPerPage;

$sql = "SELECT SQL_CALC_FOUND_ROWS * FROM jos_h_testimonials ORDER BY date DESC ".$strLimit;
// code to load some records here
// ...

// take care of pagination
$db->setQuery('SELECT FOUND_ROWS()');
$intTotalRecords = $db->LoadResult();
$this->NumberOfPages = ceil( $intTotalRecords / $intItemsPerPage);
$this->CurrentPage = $intPageNumber;
?>

テーブルスキーマ:

CREATE TABLE IF NOT EXISTS `jos_h_testimonials` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `author` varchar(255) NOT NULL,
  `testimonial` text NOT NULL,
  `rating` int(11) NOT NULL,
  `date` int(11) NOT NULL,
  `hgroup_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
)

これは、ページ形式でリストエントリを処理するための非常に標準的な方法です。私の問題は、クライアントが特別注文を望んでいることですhgroup_id。外部キーの特定の値を持つエントリが上部に表示されることを望んでいます。

私が考えることができる2つの解決策は次のとおりです。

  1. リスト全体をロードし、PHPを使用して並べ替えてから、PHPを使用してページ付けを処理します。
  2. 2つのクエリを実行します。1つは目的の外部キーを持つエントリを選択し、もう1つは他のすべての全体を選択します。結果セットをマージし、PHPを使用してページ付けを処理します。

いずれにせよ、ページネーションに対する私のエレガントな単一クエリSQL_CALC_FOUND_ROWSアプローチは機能しません。ORDER_BY句で使用できるMySQLの「魔法」があるかどうか知りたいですか?

上記が理にかなっていることを願っています。

4

2 に答える 2

3

単純なSQLを使用します。

SELECT SQL_CALC_FOUND_ROWS *
FROM jos_h_testimonials
ORDER BY
    -- Special case on top
    CASE WHEN hgroup_id = 9 THEN 0
    -- All the rest
    ELSE 1 END ASC,
    -- Regular sort order
    date DESC
于 2011-11-25T12:25:58.717 に答える
1

それほどエレガントではありませんがUNION、2つのサブ選択の結果を組み合わせるために使用できます。つまり、MySQLは引き続きページ付けを処理します。ただし、MySQLは各結果全体をフェッチする必要があるため、パフォーマンスはそれほど高くありません。

于 2011-11-25T11:54:16.930 に答える