按另一个表中存在的行排序

时间:2018-12-28 07:37:44

标签: sql postgresql

我有两个没有通过外键连接的表。

一个叫message_log,另一个叫assigned_conversation

assigned_conversation还包含match_id

我下面有没有问题的查询。

SELECT m.* 
FROM   message_log m 
WHERE  m.from_id <> 'MYID' 
       AND m.to_id = 'MYID' 
       AND m.unix_timestamp = (SELECT Max(unix_timestamp) 
                               FROM   message_log 
                               WHERE  match_id = m.match_id 
                               GROUP  BY match_id) 

我唯一想更改的查询就是结果的排序方式。

是否有可能对结果进行排序,以便将match_id表中存在的assigned_conversation s放在结果的顶部,而对于match_id s assigned_conversation表中是否不存在要排序的assigned_conversation表中存在的那些?

3 个答案:

答案 0 :(得分:2)

一种选择是使用CASE表达式进行排序,该表达式检查是否可以在match_id表中找到外部查询中给定的assigned_conversation

SELECT m.* 
FROM   message_log m
WHERE  m.from_id <> 'MYID' 
   AND m.to_id = 'MYID' 
   AND m.unix_timestamp = (SELECT Max(unix_timestamp) 
                           FROM   message_log 
                           WHERE  match_id = m.match_id 
                           GROUP  BY match_id)
ORDER BY
    CASE WHEN EXISTS (SELECT 1 FROM assigned_conversation a
                      WHERE a.match_id = m.match_id)
         THEN 0 ELSE 1 END;

请注意,我们可以尝试不加入assigned_conversation,但这可能会在您的结果集中引入重复项,假设外部查询中的match_id在{{1}中可能出现多次}。使用assigned_conversation可以解决此问题。

答案 1 :(得分:0)

除了执行子查询,您还可以使用distinct来确保仅获取最新的日志条目,然后通过左键加入assigned_conversation并按首先match_id为null的顺序进行排序,然后使用m.unix_timestamp desc可以得到预期的结果一种干净高效的方式

SELECT DISTINCT m.* 
FROM   message_log m 
left join assigned_conversation ac on ac.match_id = m.match_id
WHERE  m.from_id <> 'MYID' 
       AND m.to_id = 'MYID' 
ORDER BY ac.match_id is null, m.unix_timestamp desc

答案 2 :(得分:0)

我将查询简化为:

SELECT DISTINCT ON (ml.match_id) ml.* 
FROM message_log ml 
WHERE ml.from_id <> 'MYID' AND
      ml.to_id = 'MYID' 
ORDER BY ml.match_id, ml.unix_timestamp DESC;

然后您可以将其用作子查询来获取所需的最终订单:

SELECT ml.*
FROM (SELECT DISTINCT ON (ml.match_id) ml.*
      FROM message_log ml 
      WHERE ml.from_id <> 'MYID' AND
            ml.to_id = 'MYID' 
      ORDER BY ml.match_id, ml.unix_timestamp DESC
     ) ml
ORDER BY (EXISTS (SELECT 1 FROM assigned_conversation ac WHERE ac.match_id = ml.match_id))::int DESC,
         match_id;

但是,我倾向于将标志添加到结果集中的数据中:

SELECT ml.*
FROM (SELECT DISTINCT ON (ml.match_id) ml.*,
             (EXISTS (SELECT 1 FROM assigned_conversation ac WHERE ac.match_id = ml.match_id))::int as ac_flag
      FROM message_log ml 
      WHERE ml.from_id <> 'MYID' AND
            ml.to_id = 'MYID' 
      ORDER BY ml.match_id, ml.unix_timestamp DESC
     ) ml
ORDER BY ac_flag desc, match_id;