【问题标题】:SQL query to discover levels underneathSQL 查询以发现下面的级别
【发布时间】:2017-04-19 23:02:26
【问题描述】:

我有一个如下表结构。这只是直接(A,B,C,D和E)和间接('B1','B2','C1','C2','C3','B21'和' C31')与'X'相关,以解释问题。 实际表加载了更多与这个'X'无关的记录

(例如,桌子上可能有另一个项目“Y”,由“N”、“K”、“A”、“B1”、“B21”和“C31”组成)

表 1

Parent ChildP  SubCat  Qty
X      A       0       2
X      B       1       1
X      C       1       2
X      D       0       1
X      E       0       1
B      B1      0       1
B      B2      1       1
C      C1      0       1
C      C2      0       1
C      C3      1       1
B2     B21     0       1
C3     C31     0       1
Y      N       0       1
Y      K       1       2
Y      A       0       2
Y      B1      0       1
Y      B21     0       1
Y      C31     0       1
K      K1      0       0

我将以 Parent 'X' 作为这个问题的例子。 以下排序仅显示Parent = 'X'的位置

Table1 WHERE Parent = 'X'

Parent ChildP SubCat  Qty
X       A       0      2
X       B       1      1
X       C       1      2
X       D       0      1
X       E       0      1

现在在此表中,ChildPsSubCat 为 1 在下面有自己的 childPs。

  • 例如:SELECT * FROM Table1 WHERE Parent = 'B'

    Parent ChildP SubCat Qty
    B      B1     0       1
    B      B2     1       1
    
  • 例如:SELECT * FROM Table1 WHERE Parent = 'C'

    Parent ChildP SubCat Qty
    C      C1     0       1
    C      C2     0       1
    C      C3     1       1
    

我希望我的结果集如下所示,显示 X 的所有内容,而不仅仅是顶级 ChildPs,

Parent Level FROM  ChildP SubCat  Qty
X      1     X     A      0       2
X      1     X     B      1       1
X      1     X     C      1       2
X      1     X     D      0       1
X      1     X     E      0       1
X      2     B     B1     0       1
X      2     B     B2     1       1
X      2     C     C1     1       1
X      2     C     C2     0       1
X      2     C     C3     0       1

这些 B2 和 C1 将在它们下面有更多的子节点,这些子节点也需要显示,理想情况下最终结果如下所示:

Parent Level FROM  ChildP SubCat  Qty
X      1     X     A      0       2
X      1     X     B      1       1
X      1     X     C      1       2
X      1     X     D      0       1
X      1     X     E      0       1
X      2     B     B1     0       1
X      2     B     B2     1       1
X      2     C     C1     1       1
X      2     C     C2     0       1
X      2     C     C3     0       1
X      3     B2    B2A    0       1
X      3     C1    C1A    0       1

现在这个 B2A 和 C1A 可能在下面有更多的级别,下降到大约 5-6 级。我的问题是,我不知道每个ChildP 最初查看父级(例如:X)的级别

这就像说:显示 Parent 为 X 的所有内容,并有一个 if 子句来说明 SubCat 是否为 '1' 进一步查看直到 SubCat 为 '0'

这可以通过 SQL 查询实现吗?

【问题讨论】:

  • 您好,我确实认为这个问题与我想要的很接近,但它查看的结果表与我想要的不同?
  • 这可能不是 100% 的答案,但您应该能够采用这种方法并使用它。
  • 我希望您不打算将您的列命名为“来自”
  • 你如何找到根元素,它只是 parent = X 的元素

标签: sql sql-server


【解决方案1】:

您可以使用公用表表达式 (CTE) 执行递归 SQL Server 查询:

WITH Results(Parent, Level, [FROM], ChildP, SubCat,  Qty)
AS
(
    SELECT Parent, 1 AS Level, Parent AS [FROM], ChildP, SubCat, Qty
    FROM Table1
    UNION ALL
    SELECT r.Parent, r.Level + 1 AS Level, t.Parent, t.ChildP, t.SubCat, t.Qty
    FROM Table1 t
    INNER JOIN Results r ON t.Parent = r.ChildP
)
SELECT Parent, Level, [FROM], ChildP, SubCat,  Qty
FROM Results
WHERE Parent = 'X'
ORDER BY Level

还请查看MSDN article 关于此问题。

为了分解这个具有递归步骤的单行的特定示例,我们假设您的表中只有 X 和 B。 CTE 的第一部分(锚点)将从表中选择行并将结果排列如下:

"Columns in Results": Parent, Level, [FROM], ChildP, SubCat, Qty
"Columns in Table1":  Parent, ./.  , Parent, ChildP, SubCat, Qty
"Values":             'X'   , 1    , 'X'   , 'B'   , 1     , 1

然后它将执行一个 UNION ALL 查询 Table1 和一个 JOIN 以及第一部分中获得的上一个结果

"Columns in Results":          Parent, Level, [FROM], ChildP, SubCat, Qty
"Columns of B (from Table1)":                 Parent, ChildP, SubCat, Qty    
"Values of B (from Table1)":                  'B'   , 'B1'  , 0     , 1
"Columns of X (from Results)": Parent, Level
"Values of X (from Results)":  'X'   , 1+1=2

对于您的整个数据集,这将一直持续到您的所有行都被覆盖为止。那是因为已经递归确定的第二行也是结果集的一部分,用于进一步递归。

【讨论】:

  • 您好,我已经在一个最多有 5 个级别的表上运行了它,它给了我很多重复项。知道为什么吗?
  • Sinnerv:您的数据库是否包含重复项? WHERE Parent = 'X' 条件的作用是只获取带有父“X”的项目,因此如果您有多个项目,它们将出现在查询结果中。什么会完全搞砸结果是你也有重复的ChildP 值的孩子。也许您可以指定确切的重复项是什么...
  • 好吧,如果您在表(表 1)中查询 WHERE Parent = 'X',它将显示我在问题顶部给出的表 1 示例。所以,是的,表 1 中的 Given 'X' 有多行,我希望查询做的是识别进一步分解为较低级别并显示它们的子元素。
  • @Sinnerv:但据我所知,如果每行在结果集中出现一次,则不认为是重复的。这些行是多次出现还是其他行?
  • Contd:例如,如果我查询表 1 的 WHERE Parent = 'B' 表将有 B1 和 B2 作为 ChildPs 和 Parent 将是 B 并且在下一个级别它需要弄清楚如果其中任何一个在下面有级别。如果有,请显示它们。完成后,进入下一个级别并完成初始 ChildP 的整个列表。希望这能解释。谢谢
【解决方案2】:

这里使用递归 CTE:

设置

CREATE TABLE #table1
(
   Parent VarChar(50),
   ChildP VarChar(50),
   SubCat Int,
   Qty Int
)

INSERT INTO #table1 
Values ('X', 'A', 0,2),
        ('X', 'B', 1, 1),
        ('X', 'C', 1, 2),
        ('X', 'D', 0, 1),
        ('X', 'E', 0, 1),
        ('B', 'B1', 0, 1),
        ('B', 'B2', 1, 1),
        ('C', 'C1', 1, 1),
        ('C', 'C2', 0, 1),
        ('C', 'C3', 0, 1),
        ('B2', 'B2A', 0, 1),
        ('C1', 'C1A', 0, 1)

查询

;With CTE
As
(
    SELECT t1.Parent, 1 As Level, t1.Parent As [From], t1.ChildP, t1.SubCat,t1.Qty
    FROM #Table1 t1
    WHERE t1.Parent = 'X'
    UNION ALL
    SELECT CTE.parent, CTE.Level + 1, t2.Parent, t2.ChildP, t2.SubCat,t2.Qty 
    FROM #Table1 t2
    INNER JOIN CTE 
        ON t2.Parent = CTE.ChildP
)
SELECT *
FROM CTE
ORDER BY Parent, [Level], [From]

结果

Parent  Level   From    ChildP  SubCat  Qty
     X      1      X    A            0    2
     X      1      X    B            1    1
     X      1      X    C            1    2
     X      1      X    D            0    1
     X      1      X    E            0    1
     X      2      B    B1           0    1
     X      2      B    B2           1    1
     X      2      C    C1           1    1
     X      2      C    C2           0    1
     X      2      C    C3           0    1
     X      3      B2   B2A          0    1
     X      3      C1   C1A          0    1

【讨论】:

  • 您好,我已经在一个最多有 5 个级别的表上运行了它,它给了我很多重复项。知道为什么吗?
  • @Sinnerv 请提供真实的样本数据来证明这一点,否则我们只是在黑暗中拍摄!
  • @Sinnerv 如果您不想重复,但您的数据包含重复项,那么您可以将 Select * FROM CTE 更改为 SELECT DISTINCT * FROM CTE
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-11
  • 1970-01-01
  • 2018-08-12
  • 1970-01-01
  • 2013-06-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多