首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >复杂sql order by

复杂sql order by
EN

Stack Overflow用户
提问于 2009-08-08 22:44:44
回答 4查看 7.4K关注 0票数 7
代码语言:javascript
复制
id    |    message    |    reply id    |    date  

1     |  my new app.. |     0          | 10 / 10 / 2009 (latest message on top, follow by replies)
5     | love ur app.. |     1          | 11 / 10 / 2009 (this should show under the main message)
6     | another comm  |     1          | 12 / 10 / 2009
2     | application 2 |     0          | 09 / 10 / 2009
3     | reply of 2    |     2          | 11 / 10 / 2009

我想在主要评论之后显示最新的评论和它的回复。显然,回复将有最新的日期,所以我不能按日期排序,因为回复将在main之上。我不确定如何用一个查询正确地完成这项工作。任何想法都可以。

数据库转储:http://pastie.org/576963

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-08-09 16:31:50

我猜“回复id”对于文章是0,对于评论是文章编号。如果这就是你的设计,这应该是可行的:

代码语言:javascript
复制
select * from yourTable
order by
  case when "reply id" = 0 then id else "reply id" end, id

补充道:感谢你在评论中提供的额外信息。按照您想要的顺序放置结果并不容易,因为第一个排序键是线程启动器post的created_date。这不在数据行中,因此您需要一个联接。以下是我基于附加信息的最佳猜测(这些信息仍然不够完整,不足以让我不去猜测):

代码语言:javascript
复制
select
  f.id, f.user_id, f.type, f.reply_id, f.text, f.url, f.created_date,
  coalesce(parentfeed.created_date,f.created_date) as thread_date
from feed as f left outer join feed as parentfeed
on f.reply_id = parentfeed.id
order by
  thread_date desc,
  case when f.reply_id = 0 then 0 else 1 end,
  created_date desc, id;

您可能需要调整postgre的语法。我在SQL Server中对此进行了测试。

如果这仍然不能满足您的需要,请具体说明您希望如何恢复数据。最好,告诉我转储文件中的数据应该看到的"id“顺序,并解释该顺序的基础。下面是我所做的:

线程中的所有消息(=a消息及其注释)都应该以线程的形式进行分组,将消息放在最上面,然后按相反的时间顺序添加注释。( together.

  1. Within
  2. a message together.
  3. Within
    1. )具有最近创建的/_ created_date的线程应该是第一个,然后是具有第二个最近日期的线程,依此类推。(您的示例数据有许多具有相同created_date的注释,因此我使用"id“作为线程中注释的次序键。)

注意:你的转储表明,如果一个帖子被修改,created_date将被更新为CURRENT_TIMESTAMP。如果这是一个实时留言板,请注意这可能会导致评论在父消息之前注明日期,这意味着如果经常修改一个线程(即使它的文本没有实际更改),它将保持在顶部。(这与我的解决方案无关,但我认为它值得注意。)

因为需要一个连接,所以这个查询现在会慢很多。我的建议是:维护两个日期列"thread_last_modified“和"item_last_modified”。您必须将更新从线程启动器级联到注释,但我认为如果没有太多的更新,这是值得的,因为查询可以简单得多。我没有对此进行测试,因为它需要对您的设计进行几处更改:

代码语言:javascript
复制
select
  id, user_id, type, reply_id, text, url, thread_last_modified, item_last_modified
from feed
order by
  thread_last_modified desc,
  case when f.reply_id = 0 then 0 else 1 end,
  item_last_modified desc, id;

添加了#2:如果你只想要包含id ::thisOne注释的线程,我认为你可以在ON和ORDER BY子句之间添加下面这一行(对于我添加的第一个解决方案,连接):

代码语言:javascript
复制
where parentfeed.id = (
  select coalesce(reply_id,id)
  from feed
  where id = ::thisOne
)

从理论上讲,这个查询应该只计算一次,但是如果它不是实际的,您可以将它预先计算为::thisOneThreadID并添加

代码语言:javascript
复制
where parentfeed.id = ::thisOneThreadID

对于第二种解决方案,假设您再次预先计算,请尝试

代码语言:javascript
复制
where coalesce(id,reply_id) = ::thisOneThreadID

顺便说一句,我怀疑我的两个解决方案都会合并上次在同一时间修改的线程……

票数 8
EN

Stack Overflow用户

发布于 2009-08-08 23:13:17

……order by (对于"main comments“是真的,但对于后续则不是) desc, date desc

既然你没有明确说明“主要评论”的区别,那就是我能为你做的一切。如果像您的示例中一样,所有主注释的reply_id都为零,则可能是:

order by case reply_id = 0 then 1 else 0 end desc, date desc

请注意,使用case语句而不仅仅是sorted reply_id是必要的,因为您希望第一个表达式对所有非main消息都有相同的值(即,0),以便按第二个表达式date排他地对它们进行排序。

(哦,如果我理解您的模式,应该将reply_id命名为in_repky_to_id。)

票数 2
EN

Stack Overflow用户

发布于 2009-08-08 23:14:44

我不确定你的需求,所以我的回答是抽象的……最大值-可能需要一个最小值(同样,我不清楚您的确切要求)

代码语言:javascript
复制
select
    y.column1
    , y.column2
    , y.column3
    , y.datecolumn
from
(select 
    column1
    , max(datecolumn) as rank_date
 from tableA
 group by column1) as x
inner join tableA y on x.id = y.id
order by x.rank_date, y...., y.... desc, y... asc, etc...

如果您使用的是sql server,也可以使用一个名为over row_number的函数。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1250070

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档