【问题标题】:Sql join 1 instanceSql 连接 1 个实例
【发布时间】:2014-03-18 10:04:13
【问题描述】:

我需要一些帮助来解决我非常不稳定的 sql 技能。

假设我有以下选择语句:

SELECT DISTINCT
    p.ProjectId,
    p.Title,
    i.Name,
    p.StartDate,
    p.EndDate,
    ped.ProjectEthicsDocumentId,
    st.Description AS StatusText
FROM
    dbo.Project p
    inner join dbo.WorkflowHistory w ON p.ProjectId = w.ProjectId
    left join dbo.ProjectInstitution pi ON pi.ProjectId = p.ProjectId
    left join dbo.Institution i ON i.InstitutionId = pi.InstitutionId
    left join dbo.ProjectEthicsDocument ped on p.ProjectId = ped.ProjectId
    left join dbo.Status st ON p.StatusId = st.StatusId

这将从相关表格中返回所有项目和其他相关详细信息。现在,假设我有 2 个机构用于“项目 A”。此语句将为“项目 A”返回 2 行,每个机构一个。如何设置它以便它只返回它找到的每个项目的第一行?我想要每个项目的一个实例,比如找到的第一个机构。

【问题讨论】:

    标签: sql sql-server select join distinct


    【解决方案1】:

    最简单的方法可能是使用row_number() 函数:

    select *
    from (SELECT DISTINCT p.ProjectId, p.Title, i.Name, p.StartDate,p.EndDate,
                 ped.ProjectEthicsDocumentId, st.Description AS StatusText,
                 row_number() over (partition by p.ProjectId order by i.InstitutionId) as seqnum
          FROM dbo.Project p
               inner join dbo.WorkflowHistory w ON p.ProjectId = w.ProjectId
               left join dbo.ProjectInstitution pi ON pi.ProjectId = p.ProjectId
               left join dbo.Institution i ON i.InstitutionId = pi.InstitutionId
               left join dbo.ProjectEthicsDocument ped on p.ProjectId = ped.ProjectId
                left join dbo.Status st ON p.StatusId = st.StatusId
         ) p
    where seqnum = 1;
    

    【讨论】:

    • 这只有在其他连接不会导致更多重复时才有效。
    • @Szymon 。 . .你能详细说明吗?无论查询产生的行数如何,这都会为每个项目返回一行。
    • 我的意思是其他连接,例如到dbo.ProjectEthicsDocument 可能会为单个项目生成重复项,因为每个项目的dbo.ProjectEthicsDocument 中可能有很多行。每个项目可能需要返回多于一行,但只能返回一个机构。
    • @Szymon 。 . .至少对我来说,这个问题似乎模棱两可,但我完全理解你的解释(它似乎与 OP 真正想要的一致)。
    • 我同意这不是很清楚。我会说,您的解决方案适用于大多数情况。我认为它是一个好的。
    【解决方案2】:

    您可以将选择机构名称移至子查询。这样你就不会影响其他表的连接方式。

    SELECT DISTINCT
        p.ProjectId,
        p.Title,
        (SELECT TOP 1 i.Name FROM dbo.Institution i 
         INNER JOIN dbo.ProjectInstitution pi ON i.InstitutionId = pi.InstitutionId
         WHERE pi.ProjectId = p.ProjectId) AS Name,
        p.StartDate,
        p.EndDate,
        ped.ProjectEthicsDocumentId,
        st.Description AS StatusText
    FROM
        dbo.Project p
        inner join dbo.WorkflowHistory w ON p.ProjectId = w.ProjectId
        left join dbo.ProjectEthicsDocument ped on p.ProjectId = ped.ProjectId
        left join dbo.Status st ON p.StatusId = st.StatusId
    

    【讨论】:

      【解决方案3】:

      你可以使用

      ;with cte as
      (
      <your select statement> `,`
          Row_number() over(partition by <column that has 2 records> order by ProjectId) as rn
      )
      --then do this
       select * from cte where rn=1
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-28
        相关资源
        最近更新 更多