1

私のウェブサイトには一種の Facebook 風の好き嫌いシステムがあり、特定の投稿の好き嫌いを取得するために次のクエリを使用しています。

SELECT DISTINCT * FROM posts WHERE cid='$cid' AND pid=".implode(" OR pid=",$pids)." ORDER BY time DESC

$pid検索する投稿 ID の配列です。

zbid現在ページにアクセスしているユーザーの ID です。ここで、そのユーザーが投稿を評価 (高評価/低評価) した場合、その結果が最初に返され、その後、結果が で並べ替えられtime DESCます。

これを行うには、クエリをどのように変更しますか?

postsテーブルに次のデータがある場合:

+----+-----+------+-----+--------+------+
| | ID | シド | zbid | ピッド | 評価 | 時間 |
+----+-----+------+-----+--------+------+
| | 1 | 1 | 1 | 1 | 1 | 1 |
+----+-----+------+-----+--------+------+
| | 2 | 1 | 2 | 1 | -1 | 4 |
+----+-----+------+-----+--------+------+
| | 3 | 1 | 3 | 2 | 1 | 2 |
+----+-----+------+-----+--------+------+
| | 4 | 2 | 4 | 1 | -1 | 3 |
+----+-----+------+-----+--------+------+
| | 5 | 1 | 5 | 1 | 1 | 8 |
+----+-----+------+-----+--------+------+
| | 6 | 1 | 6 | 1 | -1 | 7 |
+----+-----+------+-----+--------+------+

現在の select ステートメント (上記) は、次の情報を返します (とともに$pid = array(1);):

+----+-----+------+-----+--------+------+
| | ID | シド | zbid | ピッド | 評価 | 時間 |
+----+-----+------+-----+--------+------+
| | 5 | 1 | 5 | 1 | 1 | 8 |
+----+-----+------+-----+--------+------+
| | 6 | 1 | 6 | 1 | -1 | 7 |
+----+-----+------+-----+--------+------+
| | 2 | 1 | 2 | 1 | -1 | 4 |
+----+-----+------+-----+--------+------+
| | 4 | 2 | 4 | 1 | -1 | 3 |
+----+-----+------+-----+--------+------+
| | 1 | 1 | 1 | 1 | 1 | 1 |
+----+-----+------+-----+--------+------+

ただし、 を持つ人zbid=4がページにアクセスしている場合は、その結果 (存在する場合) を以下のように一番上に上げる必要があります。

+----+-----+------+-----+--------+------+
| | ID | シド | zbid | ピッド | 評価 | 時間 |
+----+-----+------+-----+--------+------+
| | 4 | 2 | 4 | 1 | -1 | 3 |
+----+-----+------+-----+--------+------+
| | 5 | 1 | 5 | 1 | 1 | 8 |
+----+-----+------+-----+--------+------+
| | 6 | 1 | 6 | 1 | -1 | 7 |
+----+-----+------+-----+--------+------+
| | 2 | 1 | 2 | 1 | -1 | 4 |
+----+-----+------+-----+--------+------+
| | 1 | 1 | 1 | 1 | 1 | 1 |
+----+-----+------+-----+--------+------+

変数は、ページにアクセスして$zbidいるユーザーに設定されます。zbid

4

2 に答える 2

1

これは、あなたが提供した情報を使用して、私が思いつくことができるかなり大まかな解決策です。

解決策1-ポータブルな方法

-- This query will return User's posts and give it a higher priority in ordering, via post_order field
SELECT 
  posts.*
  ,0 as post_order
FROM posts
WHERE
  (cid='$cid' AND pid=".implode(" OR pid=",$pids).") AND
  (zbid = $user_zbid)

UNION ALL

-- This query will return everything BUT User's posts and give it a lower priority in ordering
SELECT 
  posts.*
  ,1 as post_order
FROM posts
WHERE
  (cid='$cid' AND pid=".implode(" OR pid=",$pids).") AND
  (zbid <> $user_zbid)
ORDER BY
  post_order -- This clause will put User's posts before the others
  ,time DESC

解決策2-よりパフォーマンスの高い方法(提案のためにcbranchするクレジット)

SELECT 
  posts.*
  ,IF(zbid = $user_zbid, 0, 1) as post_order
FROM posts
WHERE
  (cid='$cid' AND pid=".implode(" OR pid=",$pids).")
ORDER BY
  post_order -- This clause will put User's posts before the others
  ,time DESC


-お気づきかもしれませんが、理由がわからなかったため、SELECTからDISTINCTを削除しました。単一のテーブルからデータを抽出するだけなので、重複することはありません。もちろん、それらを追加し直すことはできますが、本当に必要な場合を除いて、そのような句を使用しないことを忘れないでください。
--2番目のクエリは、「等しくない」句を使用するため、実行に非常にコストがかかります。これは、インデックスを使用しないことを意味し、大量のデータには適していません。大きなテーブルを処理する必要がある場合は、このソリューションを確認する必要があります。

于 2012-08-08T18:14:58.663 に答える
0

ディエゴの提案を検討した後、私はうまくいった次の答えを思いつきました:

SELECT zbid,pid,rating,0 as post_order,time
    FROM posts
    WHERE cid='$cid'
        AND (pid=".implode(" OR pid=",$pids).")
        AND zbid!='$zbid'
UNION
SELECT zbid,pid,rating,1 as post_order,time
    FROM posts
    WHERE cid='$cid'
        AND (pid=".implode(" OR pid=",$pids).")
        AND zbid='$zbid'
ORDER BY
    post_order DESC,
    time DESC
于 2012-08-08T23:55:31.370 に答える