如何使用2个不同的ORDER BY语句形成MySQL查询

如何使用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的顺序返回结

我在我的网站上有一个类似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 | +----+-----+------+-----+--------+------+ 但是,如果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实际上,第二个解决方案在非常大的表上可能更快,但可移植性较差。