在SQL Server存储过程中的父行下显示子行

时间:2016-09-21 16:10:32

标签: sql sql-server ssms

有一个表格,其中包含有关存储在其中的项目的信息。每个项目都有一个ID列(FPNNumber)和一个父ID列。如果项目具有父项目,则用户选择要在该行的父项目单元格中转到的父项目的ID号。如果它没有父项目,那么父项目列将为0.我在这里看到的一些类似于我的问题,但看起来他们都使用了我不喜欢的级别列。 ; t或者想要在我的查询中使用。

我从数据库中获取数据的存储空间如下所示:

;WITH Parents
AS(
   SELECT h.[Priority]
  ,h.[FPNNumber]
  ,h.[ProjectName]
  ,sp.SponsorName
  ,pm.ProjectManagerName
  ,o.[OrgName]
  ,HealthID
  ,[StrategicAlignmentID] + [FinancialAlignmentID] + [TechnologyAlignmentID] As ProjectScore
  ,h.[Cost]
  ,h.[Budget]
  ,h.[PercentComplete]
  ,Convert(varchar(10),h.[EstimatedImpDt], 101) As EstimatedImpDt
  ,[EstimatedROI]
  ,h.[ExpectedBenefit]
  ,CONVERT(Decimal(10, 2),((DATEDIFF(day, h.[PaybackPerioddt], GETDATE()))/365.0)) As PaybackPerioddt

FROM [FPN].[ProjectNew].[Header] h
  join ProjectNew.Sponsor sp ON h.SponsorID = sp.SponsorID
  join ProjectNew.ProjectManager pm ON h.ProjectManagerID = pm.ProjectManagerID
  Join ProjectNew.Organization o ON h.OrgID = o.OrgID
  WHERE StatusID is null or StatusID < 12 and h.ParentID = 0
Union All
  SELECT he.[Priority]
  ,he.[FPNNumber]
  ,he.[ProjectName]
  ,sp.SponsorName
  ,pm.ProjectManagerName
  ,o.[OrgName]
  ,he.HealthID
  ,[StrategicAlignmentID] + [FinancialAlignmentID] + [TechnologyAlignmentID] As ProjectScore
  ,he.[Cost]
  ,he.[Budget]
  ,he.[PercentComplete]
  ,Convert(varchar(10),he.[EstimatedImpDt], 101) As EstimatedImpDt
  ,he.[EstimatedROI]
  ,he.[ExpectedBenefit]
  ,CONVERT(Decimal(10, 2),((DATEDIFF(day, he.[PaybackPerioddt], GETDATE()))/365.0)) As PaybackPerioddt

FROM [FPN].[ProjectNew].[Header] he
  join ProjectNew.Sponsor sp ON he.SponsorID = sp.SponsorID
  join ProjectNew.ProjectManager pm ON he.ProjectManagerID = pm.ProjectManagerID
  Join ProjectNew.Organization o ON he.OrgID = o.OrgID
  Join Parents cte on cte.FPNNumber = he.ParentID
WHERE StatusID is null or StatusID < 12
)
Select * from Parents

我曾尝试过部分工作,但并不是我需要的工作

 ID | ParentID
----------------
 1  | 0
 2  | 0
 4  | 2
 5  | 2
 3  | 1
 6  | 1
 7  | 1

当我执行时,结果如下:

 ID | ParentID
----------------
 1  | 0
 3  | 1
 6  | 1
 7  | 1
 2  | 0
 4  | 2
 5  | 2

我需要它看起来像这样:

public class Product 
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public double Price { get; set; }
    public int CategoryId { get; set; }
    public ICollection<Part> Parts { get; set; }
}

public class Part
{
    public int PartId { get; set; }
    public int ProductId { get; set; }
    public Product Product { get; set;}
}

因此,ID为2的行下面有两个相应的子项目,但ID 1的子项目低于该项目。

我做错了什么?有没有办法让所有子项目在其父项目下显示?如果是这样,有没有办法做到这一点,然后当我将这些数据调用到Visual Studio中的ListView时,如果用户单击一个排序按钮,那么它是否不会加扰子项目?

3 个答案:

答案 0 :(得分:3)

Select * from Parents
ORDER BY
    CASE WHEN ParentId = 0 THEN Id ELSE ParentId END
    ,ID

有趣的是,这个问题似乎仍然得到了一些关注,所以我会稍微扩展一下我的叙述,以便更清楚地了解递归期间发生的事情。

您的锚表开始并抓取2行,它将这些行保存在内存中,然后将这两行中的每一行连接到它们的子行,然后在下一次迭代中将这些子项连接到它们的子项。所以它同时遍历所有的谱系,而不是一次遍历,这就是为什么你得到显示的顺序。等级0首先然后是等级1,2等等

因此,如果您希望以特定顺序(例如父级,然后是子级)获得结果,则必须告诉sql使用order by语句对它们进行排序。在您的特定情况下,由于您在递归期间识别并继续使用ParentId的方式,您需要使Parentless Parent(0)等于其自身,然后按ID排序。这可以在案例表达式中完成,如上所示。

答案 1 :(得分:0)

如果我理解你的问题,似乎你想确保层次结构的顺序正确。

以下是一般样本使用在这种情况下使用基于标题的序列,但可以是任何可用字段。

此外,范围键是完全可选的。 (如果不需要,删除cteR1和cteR2)

df['A'] = df['A'].apply(lambda x: np.array(x))
df.apply(lambda x: print(x[0],(x[1],x[2])) ,axis=1)
df['A_reshaped'] = df.apply(lambda x[['A','R','C']]: np.reshape(x[0],(x[1],x[2])),axis=1)
df

       A                    C    R           A_reshaped
0   [10, 15, 12, 14]    2   2        [[10,15],[12,14]]
1   [20, 30, 10, 43]    2   2        [[20,30],[10,43]]

返回

enter image description here

答案 2 :(得分:-1)

您可以尝试类似于以下堆栈溢出问题中提供的解决方案:

Query to get parent records with child record, followed by next parent-child records in mysql

或者您可以尝试以下解决方案。

我在下面提供了我的解决方案,以获得您想要的订单。我已将 rnk 用作附加列,您可以在最终结果集中忽略该列。

CREATE TABLE #ParentChild (
    projectId INT
    ,parentProjectId INT
    )

INSERT INTO #ParentChild
VALUES (1,0),(2,0),(3,1),(4,1),(5,1),(6,2),(7,2),(8,2);

SELECT projectid
    ,parentprojectid
    ,row_number() OVER (
        PARTITION BY parentconsider ORDER BY projectid
        ) AS rnk
FROM (
    SELECT projectId
        ,parentProjectId
        ,CASE 
            WHEN parentProjectId = 0
                THEN projectId
            ELSE parentProjectId
            END AS parentconsider
    FROM #ParentChild
    ) AS x