我的网站上有一种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 | cid | zbid | pid | rating | time | +----+-----+------+-----+--------+------+ | 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 | cid | zbid | pid | rating | time | +----+-----+------+-----+--------+------+ | 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 | cid | zbid | pid | rating | time | +----+-----+------+-----+--------+------+ | 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
。
答案 0 :(得分: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,因为我看不出它们的原因。由于您只是从单个表中提取数据,因此您不应该有重复项。显然,您仍然可以添加它们,但请记住不要使用此类条款,除非确实需要它
- 第二个查询运行起来非常昂贵,因为它使用&#34;不等于&#34;条款。这意味着它不会使用索引,并且它不适合大量数据。如果您必须处理大表,则必须审查此解决方案。
答案 1 :(得分: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