2011-02-01 8 views
8

私はproductsというテーブルをMySQLデータベースに持っています。SQL:where句の次の行を見つけて

id name  din  strength active deleted 
1 APA TEST 00246374 25  1  0 
4 APA BOB 00246375 50  1  0 
5 APA TIRE 00246888 50  1  0 
7 APA ROT 00521414 100  1  0 
9 APA APA 01142124 100  1  0 
6 APA CODE 00121212 150  1  0 
8 APA SERV 00011145 600  1  0 

もちろん、私は私の質問には重要ではないいくつかの列を残してきた:productsは、このようないくつかは何に見えます。私はこのテーブルを照会するとき、私はいくつかの異なる列の1つでソートします(ユーザーインターフェイスで個々のユーザーが並べ替えの列と順序を変更できるようになります)。検索句がある場合はLIKE句をNAMEとDIN。

私が知りたいのは、ソート情報と検索情報、および特定の製品のIDが与えられていることです(私は、3つの結果を返した004を検索し、そのうちの1つを見ています)次の製品や前の製品を入手できますか?

結果を検索してソートした後にユーザーが編集/表示するためにクリックすると、前のページに移動せずに結果を循環させたいからです。

SQLでこれを行うには効率的な方法がありますか、それともPHPを使うのが一番ですか?どんなアイデアも歓迎します。現在、私は、ソートstrength列での重複値

SELECT T.* 
FROM `wp_products` T 
INNER JOIN `wp_products` curr on curr.id = 38 
    AND ((T.strength = curr.strength and T.id < curr.id) 
    OR (T.strength > curr.strength)) 
WHERE T.active = 1 AND T.deleted = 0 AND (T.name LIKE '%%' OR T.din LIKE '%%') 
ORDER BY T.strength ASC, T.id ASC 
LIMIT 1 

は(次の項目を取得するために設計された)(ワードプレスを使用して)私のPHPコード

があるようならば問題が発生している。このSQLクエリを使用して、

$sql = 'SELECT T.* 
FROM `' . $wpdb->prefix . 'apsi_products` T 
INNER JOIN `' . $wpdb->prefix . 'apsi_products` curr on curr.id = ' . $item->id . ' 
    AND ((T.' . $wpdb->escape($query['orderby']) . ' = curr.' . $wpdb->escape($query['orderby']) . ' and T.id > curr.id) 
    OR (T.' . $wpdb->escape($query['orderby']) . ' > curr.' . $wpdb->escape($query['orderby']) . ')) 
WHERE T.active = 1 AND T.deleted = 0 AND (T.name LIKE \'%' . $query['where'] . '%\' OR T.din LIKE \'%' . $query['where'] . '%\') 
ORDER BY T.' . $wpdb->escape($query['orderby']) . ' ' . $query['order'] . ', T.id ASC 
LIMIT 1;'; 

答えて

5

現在のレコードへの参照を持つ必要があります。次のレコードは、並べ替えられた列に基づいて徐々に探します。以下の例は、それが

ORDER BY Active, DIN, NAME 

最初にソートされている前提としています

SELECT * 
FROM TABLE 
WHERE NAME LIKE '%X%' AND DIN LIKE '%%' 
ORDER BY Active, DIN, Name 
LIMIT 1; 

次:(あなたは正しいブラケットCURR.ID = 6を分離し、AND-ORを作る!)

SELECT * 
FROM TABLE T 
INNER JOIN TABLE CURR ON CURR.ID = 6 # the current ID being viewed 
    AND ((T.Active = Curr.Active AND T.DIN = Curr.DIN AND T.NAME > Curr.Name) 
    OR (T.Active = Curr.Active AND T.DIN > Curr.DIN) 
    OR T.Active > Curr.Active) 
WHERE T.NAME LIKE '%X%' AND T.DIN LIKE '%%' 
ORDER BY T.Active, T.DIN, T.Name 
LIMIT 1; 

以下に示す作業サンプル

create table products 
(ID int, SEED int, NAME varchar(20), DIN varchar(10), ACTIVE int, DELETED int); 
insert products values 
(1, 0, 'Product #1', '004812', 1, 0), 
(2, 0, 'Product #2', '004942', 0, 0), 
(3, 0, 'Product #3', '004966', 1, 0), 
(4, 0, 'Product #4', '007437', 1, 1), 
(5, 2, 'Product #2', '004944', 0, 0), 
(6, 2, 'Product #2', '004944', 1, 0); 

SELECT * 
FROM products 
WHERE active = 1 AND deleted = 0 
ORDER BY din DESC, ID desc; 

Output: 
"ID";"SEED";"NAME";"DIN";"ACTIVE";"DELETED" 
"3";"0";"Product #3";"004966";"1";"0" 
"6";"2";"Product #2";"004944";"1";"0" 
"1";"0";"Product #1";"004812";"1";"0" 

電流はID = 6を有する行である場合、次のレコードは、それが1つのクエリで行うことができる

SELECT T.* 
FROM products T 
INNER JOIN products curr on curr.ID = 6 
    AND ((T.din = curr.din and T.ID > curr.ID) 
    OR (T.din < curr.din)) 
WHERE T.active = 1 AND T.deleted = 0 
ORDER BY T.din DESC, T.ID ASC 
LIMIT 1; 
+0

申し訳ありませんが、私はいつもSQLにひどいことをしてきました。 CURRへの参照をそのまま残すか、CURRとTABLEをテーブル名に変更する必要がありますか? –

+0

TABLEは、テーブル名のプレースホルダです。 CURRとTはエイリアスです。それらをそのままにしておきます。 – RichardTheKiwi

+0

私はあなたの質問なしに成功していない、私は間違って何かをやっている可能性があります。私のクエリは次のようになります: 'SELECT * FROM table_name WHERE active = 1 AND deleted = 0 ORDER BY din DESC'そして、クエリを実行すると、返された5番目のIDを使用していても、 。 6番目のIDからID 38を取得する必要があります。アイデア? –

0

興味深い質問。私はあなたが1つのクエリでそれを行うことはできないと思っていますが、おそらく3つでそれを取り除くことができます。

最初のクエリは応答行を取得します。そのトリックは、並べ替えられた列の値を保持することです。これが "SortedColumn"で、値が "M"であるとしましょう。あなたが持っている行のIDが10だったとしましょう。

2番目のクエリは最初のクエリと同じですが、 "トップ1"になり、where句に追加されます "...とsortedColumn> = ' M 'とid <> 10 "これで次の行が得られます。これを何度もやり直すことを防ぐために、10行を戻してそれらを保持することができます。

これを得るには、注文を降順に切り替え、追加するwhere句は "... and sortColumn < = 'M'かつid <> 10"です。これは前の行を取得します。ここでも、10行がユーザーにとってより有用な場合があります。

これが役に立ちます。

+0

を使用して取得することができます。私の答えを参照してください – RichardTheKiwi

+0

私はすぐにこれを試して、私はそれが動作するとは思わない。名前欄でソートしているとします。 'name'> = 'PRODUCT NAME#3'の部分は動作しないようです。 –

+0

@cyberwiki:nice。 –

1

memcachedのような永続性キャッシュ層がないと、結果を保存してクエリを再発行せずに取得できるため、単純な解決策でmysqlのquery cacheを有効にできます。このようにキャッシュが他のquerysから無効にされていない場合は、クエリを再発行する場合、結果を引っ張ってのコストがそれぞれ表示された結果について

+0

これは1つのクエリを使用して効率的に行うことができます。私の質問を理解してから私の答えを – RichardTheKiwi

+0

@cyberwiki参照してください。項目は異なるページからリクエストされるため、クエリーの問題は1つではありません。あなたのクエリは、さまざまなアイテムを検索する方法を扱いますが、各ページ要求に対して再評価されます。同意しますか? – Ass3mbler

+0

はい、ただし、適切なインデックス付けを行うと、各制限1は必要に応じて効率的に1レコードしか取得しません。各SOページのロードは少なくともdbから約10個のアイテムを要求するため、ラウンドトリップは軽度の懸念事項です。 – RichardTheKiwi

1

を低下させることになる、セットアップと以前リンク適切なID。

詳細ビューからソート順を変更することはできません。

関連する問題