如何通过列I来选择两个带有UNION的SELECT,而不是选择?

时间:2014-08-13 19:04:12

标签: mysql sql pdo mariadb

此查询有效:

 SELECT recipient_id FROM messages WHERE (sender_id=? and folder=1) 
   UNION 
     SELECT sender_id FROM messages WHERE (recipient_id=? and folder=1)

但我需要ORDER BY time DESC,无论我在哪里添加它都不起作用。如果我将, time添加到我正在选择的内容中,它会正确排序,但会改变它返回的内容。

我正在使用MariaDB。

3 个答案:

答案 0 :(得分:0)

您可以对联合排序结果集进行子选择,并仅选择所需的字段

SELECT id FROM (
SELECT recipient_id as id,time  FROM messages WHERE (sender_id=? and folder=1)
 UNION 
SELECT sender_id as id,time  FROM messages WHERE (recipient_id=? and folder=1)
ORDER BY time DESC
) t

或者,如果您想区分哪种类型的ID是发件人或收件人

SELECT id,`type` FROM (
SELECT recipient_id as id,time, 'recipient' as `type`  FROM messages WHERE (sender_id=? and folder=1)
 UNION 
SELECT sender_id as id,time ,'sender' as `type`  FROM messages WHERE (recipient_id=? and folder=1)
ORDER BY time DESC
) t

答案 1 :(得分:0)

我不知道这是否适用于MySql,但它适用于Oracle:

SELECT id,max(time) FROM (
SELECT recipient_id as id,time  FROM messages WHERE (sender_id=? and folder=1)
UNION 
SELECT sender_id as id,time  FROM messages WHERE (recipient_id=? and folder=1)
) t group by id
order by 2 desc

当然,他们是更有效的方式,也许是另一组进入工会的部分。

答案 2 :(得分:0)

UNION集合运算符将删除重复的行;如果SELECT返回具有相同recipient_id的多个行,则这些行将折叠为单个行。您需要确定您想要time值的行。

UNION ALL集合运算符类似于UNION,因为它连接结果,但它不会删除“重复”行。

您可以通过以下查询获得等效结果:

SELECT IF(m.sender_id=?,m.recipient_id,IF(m.recipient_id=?,m.sender_id,NULL)) AS x_id
  FROM messages m
 WHERE m.folder = 1
   AND (sender_id=? OR recipient_id=?)
 GROUP BY x_id
 ORDER BY MAX(m.time) DESC

(注意:这会按最新的x_id值排序time值。)

如果您真的不想消除重复项(UNION运算符在原始查询中执行的操作),如果要返回所有行,请删除GROUP BY子句并使用标量time代替ORDER BY子句中的聚合:

SELECT IF(m.sender_id=?,m.recipient_id,IF(m.recipient_id=?,m.sender_id,NULL)) AS x_id
  FROM messages m
 WHERE m.folder = 1
   AND (sender_id=? OR recipient_id=?)
 ORDER BY m.time DESC