2011-06-29 119 views
2

我有两个表Post (id, ..., creationdate)Post_Has_Post(parent_id, child_id)SQL:通过(可选)关系订购结果

某些职位可以是父母的一部分< - >子女关系,并在​​表中具有相应的条目 - 表。

我想要做的是获取由其creationdate排序的帖子列表。但是,其他职位的任何子女都应该在其父母之后插入结果。 现在当然很容易通过creationdate订购,但是我对第二种分拣条件没有想法。有没有办法做到这一点?

Post        Post_Has_Post 
+------+-------+--------------+ +-----------+----------+ 
| id | ... | creationdate | | parent_id | child_id | 
+------+-------+--------------+ +-----------+----------+ 
| 1 | ... | 2010-11-01 | | 1  | 3  | 
| 2 | ... | 2010-11-02 | +-----------+----------+ 
| 3 | ... | 2010-11-03 | 
+------+-------+--------------+ 

我需要整理这样的结果:

Post 
+------+-------+--------------+ 
| id | ... | creationdate | 
+------+-------+--------------+ 
| 1 | ... | 2010-11-01 | 
| 3 | ... | 2010-11-03 | 
| 2 | ... | 2010-11-02 | 
+------+-------+--------------+ 

是否有通过排序来解决此问题的方法?

+0

您是否允许多层次的父子关系? I.e .: 1是3的父亲,3是2的父母。这将改变的事情,以及... –

+0

另外,你的设计允许一个职位有两个父母。那么你的输出将如何? –

+0

@阿德里安你是对的,我会摆脱关系表 –

回答

4

假设父母总是在孩子面前,这应该工作。

SELECT p.id, ..., creationdate 
    FROM Post p 
     LEFT JOIN Post_Has_Post php 
      ON p.id = php.child_id 
    ORDER BY COALESCE(php.parent_id, p.id), 
      creationdate 
+0

我期待在'ORDER BY'这个'CASE',但如果它适用于OP我会把它:) – JNK

+0

这工作, 非常感谢!直到现在我还没有意识到这个功能! –

2

您不应该有表Post_Has_Parent。相反,请查看 将列添加到“parent_id”的Post表中,并使用post_id和parent_id之间的关系以及自加入。当 某人发布帖子的回复时,只需将其父帖子ID作为新帖子的parent_id 即可。这将允许您将 关系存储在一个表中。

根据的DBMS,你可以考虑使用:

甲骨文:Connect_be

select seq_num, post_text, parent_id, SYS_CONNECT_BY_PATH(seq_num, 
'/') AS PATH, level 
 from post 
start with seq_num = 1 
CONNECT BY NOCYCLE PRIOR seq_num = parent_id; 

的SQL Server:通用表表达式

;with posts as 
(

      select seq_num, post_text, parent_id, 0 AS generation, 
              CAST(seq_num as varchar(50)) as path 
              from recurs_test 
              where parent_id is NULL 
      UNION ALL 
      select e.seq_num, e.post_text, e.parent_id, generation + 1, 
              CAST(rtrim(p.path) + '/' +  CAST(e.seq_num as varchar(5)) as 
varchar(50)) as path 
              from recurs_test e 
              inner join posts p 
              on e.parent_id = p.seq_num 

) 

select seq_num, name, parent_id, dir, generation from 
managers order by dir; 

MYSQL:你将不得不看使用某种树 遍历算法并进行深度优先搜索。它们都非常复杂,通常涉及在数据库中存储某些内容(路径,左侧值和右侧值等)。原因是MYSQL不允许 允许任何递归选择语句(纠正我,如果我错了,所以我 可以重做我已经写了一些代码!!)

+0

尽管如此,它并不回答这个问题。它应该是一个评论,而不是一个答案。 –

+2

虽然这并没有解决排序的问题。也许发表一个建议,告诉你如何按照你提出的结构以所需的顺序显示。 – JNK

+0

@adrian - 他/她的代表太低评论我认为。 – JNK

1

你不会在一个列中的日期,但恕我直言,这是有点混乱无论如何。您可以选择在任何用户界面呈现数据时显示子线程日期或父线程日期:

SELECT Parent.ID, Parent.CreationDate ParentCreationDate, 
     Child.CreationDate ChildCreationDate 
FROM Post Parent LEFT OUTER JOIN 
    Post_Has_Post PHP ON Parent.ID = PHP.Parent_ID LEFT OUTER JOIN 
    Post Child ON PHP.Child_ID = Child.ID 
ORDER BY Parent.CreationDate, Child.CreationDate; 
+2

您可以使用'COALESCE(Parent.CreationDate,Child.Creationdate)AS CreationDate'将其显示在单个字段中。 – JNK

+0

@JNK:好点。实际上,我的查询应该也可以为父/子帖子ID做这件事。 – Yuck