如何使用2个不同的ORDER BY语句形成MySQL查询
我在我的网站上有一个类似Facebook的喜欢/不喜欢系统,我使用以下查询来获取特定帖子的喜欢/不喜欢:如何使用2个不同的ORDER BY语句形成MySQL查询,mysql,sql-order-by,Mysql,Sql Order By,我在我的网站上有一个类似Facebook的喜欢/不喜欢系统,我使用以下查询来获取特定帖子的喜欢/不喜欢: SELECT DISTINCT * FROM posts WHERE cid='$cid' AND pid=".implode(" OR pid=",$pids)." ORDER BY time DESC $pid是要搜索的帖子ID数组 zbid是当前正在访问页面的用户的id。现在,如果该用户对帖子进行了评分(喜欢/不喜欢),那么应该首先返回他的结果,然后按照time DESC的顺序返回结
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 |
+----+-----+------+-----+--------+------+
但是,如果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 |
+----+-----+------+-----+--------+------+
+----+-----+------+-----+--------+------+
|id | cid | zbid | pid |额定值|时间|
+----+-----+------+-----+--------+------+
| 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
根据您提供的信息,这是一个相当粗略的解决方案:
解决方案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
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,因为我看不出它们的原因。因为您只是从一个表中提取数据,所以不应该有重复的数据。显然,您仍然可以将它们添加回去,但请记住,除非确实需要,否则不要使用此类子句。
-第二个查询运行起来非常昂贵,因为它使用了“notequalto”子句。这意味着它将不使用索引,也不适用于大量数据。如果您必须处理一个大表,则必须对该解决方案进行审查。根据您提供的信息,这是一个相当粗略的解决方案: 解决方案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
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,因为我看不出它们的原因。因为您只是从一个表中提取数据,所以不应该有重复的数据。显然,您仍然可以将它们添加回去,但请记住,除非确实需要,否则不要使用此类子句。
-第二个查询运行起来非常昂贵,因为它使用了“notequalto”子句。这意味着它将不使用索引,也不适用于大量数据。如果你要处理一张大桌子,这个解决方案必须经过审查。在审查了迭戈的建议后,我想出了以下有效的答案:
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
在回顾了迭戈的建议后,我得出了以下有效的答案:
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
请再次编辑您的问题,并在查询后添加一些示例数据和所需的数据输出,以便更清楚地了解您要做什么。谢谢。:-)请再次编辑您的问题,并在查询后添加一些示例数据和所需的数据输出,以便更清楚地了解您要做什么。谢谢。:-)我认为您可以对单个查询执行相同的操作,并避免使用
联合ALL
选择IF(zbid=$userzbid,0,1)作为post_order
没错,但它的可移植性较差。我倾向于尽可能坚持使用ANSI SQL。:)但是,IF()
子句将避免讨厌的“不等于”子句,这将是一个很大的优势。@cbranch我编辑了答案,添加了您的建议,以及应得的积分。谢谢您的建议。我将在一个相对较大的表上使用它,因此我选择第一个解决方案。我以前从未使用过UNION
,所以我不熟悉它的语法。第一个解决方案是整个查询还是需要附加到我当前的查询中?@Keir实际上,第二个解决方案在非常大的表上可能更快,但可移植性较差。我认为您可以对单个查询执行相同的操作,并避免使用UNION ALL
选择IF(zbid=$userzbid,0,1)作为post_order
没错,但它的可移植性较差。我倾向于尽可能坚持使用ANSI SQL。:)但是,IF()
子句将避免讨厌的“不等于”子句,这将是一个很大的优势。@cbranch我编辑了答案,添加了您的建议,以及应得的积分。谢谢您的建议。我将在一个相对较大的表上使用它,因此我选择第一个解决方案。我以前从未使用过UNION
,所以我不熟悉它的语法。第一个解决方案是整个查询还是需要附加到当前查询中?@Keir实际上,第二个解决方案在非常大的表上可能更快,但可移植性较差。