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表有以下数据:

+----+-----+------+-----+--------+------+
| 编号 | 西德 | 出价 | 进程号 | 评级 | 时间 |
+----+-----+------+-----+--------+------+
| 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);):

+----+-----+------+-----+--------+------+
| 编号 | 西德 | 出价 | 进程号 | 评级 | 时间 |
+----+-----+------+-----+--------+------+
| 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正在访问该页面,它应该将该结果(如果存在)提升到顶部,如下所示:

+----+-----+------+-----+--------+------+
| 编号 | 西德 | 出价 | 进程号 | 评级 | 时间 |
+----+-----+------+-----+--------+------+
| 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,因为我看不到它们的原因。由于您只是从单个表中提取数据,因此不应有重复项。显然,您仍然可以将它们添加回来,但请记住,除非确实需要,否则不要使用此类子句。
- 第二个查询运行起来会非常昂贵,因为它使用“不等于”子句。这意味着它不会使用索引,也不适合处理大量数据。如果您必须处理一张大桌子,则必须审查此解决方案。

于 2012-08-08T18:14:58.663 回答
0

在查看 Diego 的建议后,我想出了以下有效的答案:

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 回答