【问题标题】:mysql group and sort a UNIONmysql 分组和排序一个 UNION
【发布时间】:2011-04-17 22:11:17
【问题描述】:

在我的留言簿中,我有 2 张桌子:messagesreplies。 现在,我想获取按 id 分组的所有消息(意味着消息和相应的回复将被分组/在一起)并按日期 DESC 排序(最新消息将排在第一位;如果消息是最旧的,但相应的回复是所有消息中的最新消息,该组将位于表格顶部),而回复将按日期 ASC 排序(最旧的回复在顶部)。 这里我的 mysql 查询效果很好,只是它没有按日期 ASC 对回复进行排序

SELECT msg.id as id, msg.comment, msg.date_added as date_added, 0 as is_reply
  FROM messages AS msg 
UNION 
SELECT reply.msg_id as id, reply.comment, reply.date_added as date_added, 1 as is_reply
  FROM pg_reply as reply 

GROUP BY id 
ORDER BY date_added DESC, is_reply ASC 

is_reply ASC 没有按照我的设想完成工作

reply.msg_id 指定回复父级的 id (messages.id)

结果应该是什么样子>

- message A
- oldest reply B 
- old reply C
- new reply Z  // this is the newest message in the guestbook 
- newer message E // is newer than A but older than the newest message in the guestbook, which is Z
- reply F // (this reply is newer than all messages but message Z)

【问题讨论】:

  • 回复如何与他们的父消息相关联?即,您如何知道回复正在回复什么消息?我没有看到任何包含此映射的字段。
  • 您使用哪个字段来链接消息及其回复?回复是否有 origmsg_id 字段?
  • @squawknull @Johan 哦,我忘了,reply.msg_id 是回复的父级

标签: mysql


【解决方案1】:

对于这个答案,我将假设reply.msg_id 是原始消息的链接字段。

SELECT id, comment, date_added, is_reply FROM (
  SELECT 
    msg.id as id
    , msg.comment
    , msg.date_added as date_added
    , 0 as is_reply
    FROM messages AS msg 
UNION 
  SELECT 
    reply.msg_id as id
    , reply.comment
    , reply.date_added as date_added
    , 1 as is_reply
  FROM pg_reply as reply ) AS allmsg
ORDER BY id DESC, is_reply, date_added DESC

假设 msg_id 是一个自动增量字段并且较新的 id 也具有较新的 date_added 时间戳,则此方法有效。

原代码备注
在您的原始代码中,您有

GROUP BY id 
ORDER BY date_added DESC, is_reply ASC

GROUP BY 隐式命令id ASC;以下ORDER BY 覆盖并按date_added 第一和is_reply 第二排序。
但是,如果 date_addeddatetime,那么两个帖子同时发布的可能性很小(尤其是对于回复,写它们需要时间),
所以二阶子句几乎没有被使用过。

GROUP BY 仅应在您的select 中有聚合函数时使用,例如SUMCOUNT

如果您想从选择的不使用组中删除重复项,请使用 distinct,如 select distinct a,b,c from table1 where ...

【讨论】:

  • 谢谢。好吧,我不知道 order by 子句仅适用于具有相等值的项目,很高兴知道
  • 是的,第二个 order by 子句仅在第一个 order by 子句开始吐出相同值时才有效。
【解决方案2】:

类似的解决方案:

SELECT sort, project, reviewdate, reviewby, subject, venue, filename, remarks1, remarks2, url
FROM (

   SELECT '1' AS sort, project, last_updated AS reviewdate, reviewby, concat( project, '(', 
    TYPE , '): ', subject ) AS subject, venue, filename, remarks1, remarks2, concat( project, '/', 
    TYPE , '/', filename ) AS url
   FROM `upload_cmg` 
   WHERE (
     (
      subject LIKE '%prt%'
      OR project LIKE '%prt%'
      OR TYPE LIKE '%prt%'
     )
     AND (
      subject LIKE '%mouda%'
      OR project LIKE '%mouda%'
      OR TYPE LIKE '%mouda%'
     )
   )
   UNION SELECT '2' AS sort, project, last_updated AS reviewdate, reviewby, concat( project, '(', 
    TYPE , '): ', subject ) AS subject, venue, filename, remarks1, remarks2, concat( project, '/', 
    TYPE , '/', filename ) AS url
   FROM `upload_cmg` 
   WHERE subject LIKE '%mouda%'
   GROUP BY url
) AS vin
ORDER BY sort, reviewdate DESC 

【讨论】:

    【解决方案3】:

    我建议在两者中添加消息父字段并将其作为主要排序进行排序,然后将日期作为之后的排序。否则,您的回复将与在回复之间发布的其他消息混在一起。您可以将非回复消息的消息父级设为自身。

    【讨论】:

      【解决方案4】:

      试试这个:

      SELECT id, comment, date_added, is_reply
      FROM (
          SELECT msg.id as id, msg.comment, msg.date_added as date_added, 0 as is_reply
            FROM messages AS msg 
          INNER JOIN pg_reply as reply
          ON reply.msg_id = msg.id
          GROUP BY msg.id, msg.comment, msg.date_added, 0 as is_reply
          ORDER BY CASE WHEN MAX(reply.date_added) > msg.date_added THEN MAX(reply.date_added) ELSE msg.date_added END DESC
          UNION 
          SELECT reply.msg_id as id, reply.comment, reply.date_added as date_added, 1 as is_reply
          FROM pg_reply as reply 
          ORDER BY date_added ASC ) a
      ORDER BY id
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-05-16
        • 2015-10-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-15
        • 2021-10-14
        • 1970-01-01
        相关资源
        最近更新 更多