【问题标题】:Three-way join using one SQL table使用一张 SQL 表进行三向连接
【发布时间】:2011-09-02 08:11:17
【问题描述】:

假设有一个 MSSQL 表 UserPost,它代表用户发布的内容,具有以下字段:

ID | dateAdded | parentPostID | postBody

系统中的一个用户可以创建一个Request,接收一个Response,然后其他用户可以CommentResponse 。即,请求 响应 评论(想想 StackOverlow 的问题 > 答案 > 评论模型)。

所有用户帖子(RequestResponseComment)由 UserPost 行表示,其中 Request 具有parentPostID = null;; Responses 的parentPostID 是Request 的ID,Comment 的parentPostID 是Response 的ID。

我需要以一种简单的方式输出所有内容:

Request 1
- Response A
-- Comment (i)
-- Comment (ii)
- Response B
-- Comment (i)
Request 2
...

问题:哪个 SQL 语句以最有用的方式返回所需的信息?

我正在努力在 (UserPosts) as Requests [join] (UserPosts) as Responses [join] (UsersPosts) as Comments 之间编写三向连接,但我不确定这是最简单的方法。

奖励:是否可以使用 C# Linq 做到这一点?

【问题讨论】:

    标签: c# sql linq sql-server-2008 join


    【解决方案1】:

    想不出在 LINQ 中执行此操作的方法。我删除了未使用的列。幸运的是,这是一个有界的层次结构。我正在使用新的hierarchyid 数据类型,它具有所需的排序顺序:

    create table UserPosts (
        ID int not null,
        ParentID int null
    )
    go
    insert into UserPosts (ID,ParentID)
    select 1,null union all
    select 2,null union all
    select 3,1 union all
    select 4,2 union all
    select 5,3 union all
    select 6,1 union all
    select 7,6
    go
    select
        *
    from
        UserPosts up
            left join
        UserPosts up_1st
            on
                up.ParentID = up_1st.ID
            left join
        UserPosts up_2nd
            on
                up_1st.ParentID = up_2nd.ID
    order by
        CONVERT(hierarchyid,
        COALESCE('/' + CONVERT(varchar(10),up_2nd.ID),'') +
        COALESCE('/' + CONVERT(varchar(10),up_1st.ID),'') +
        '/' + CONVERT(varchar(10),up.ID) + '/'
        )
    

    HierarchyID(作为字符串)看起来像 /GrandParent/Parent/Child/ - 所以我们构造的值看起来像这样。显然,如果我们没有祖父母(up_2nd.ID 为空,因为我们无法实现所描述的 2 个左连接),那么我们只想构造 /Parent/Child/ - 这就是第一个 COALESCE 正在帮助我们实现的目标.类似地,如果我们找不到任何父项(up_1st.IDup_2nd.ID 都为空),那么这两个 COALESCE 都会变成空字符串,我们最终会构造 /ID/


    您可以添加:

    CASE
        WHEN up_2nd.ID is not null then 'Comment'
        WHEN up_1st.ID is not null then 'Response'
        ELSE 'Request'
    END as Level
    

    到您的选择列表,如果您想跟踪项目的级别(或使用数字代替,如果需要)

    【讨论】:

    • 哇,谢谢,达米安!只是为了澄清 - 它们将按此字段排序,但不会出现在输出中。如何遍历 up.postBody、up_1st.postBody、up_2nd.postBody?您是否建议保持一个正在运行的int currentValue[GrandParent|Parent|Child] 来跟踪每个 ID,并在它们发生变化时,在输出页面上交替启动一个新的父/祖父组?
    • @Carl J - 我添加了一个我认为可能适合您需要的建议
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-30
    • 2012-08-03
    相关资源
    最近更新 更多