如何使用一列的数据来获取SQL SELECT语句

时间:2016-01-07 13:27:17

标签: sql sql-server

我在SQL Server 2014的表[AdjT]中存储了分层数据。数据的总深度是4级并且是固定的。
即,[父母 - 子女1 - 儿童2 - 儿童3]

列是:Adjt {Id,ParentId,Title,TypeM}
您可以在图像中看到数据。 Data in table

多个层次结构(根据TypeM)存在于同一个表中(您可以看到2个父项)

我需要什么?

我需要为任何给定的Child获取所有父“Title”。例如,下面的图像显示Id的“层次结构”:TypeM:AAA Expected Output

到目前为止我做了什么

此查询为我提供了子行及其直接父级。

select a.Title as P1, (select a1.Title from AdjT as a1 where a1.Id=a.ParentId) as P1 from Adjt as a where a.TypeM='AAA' and a.Id=4;
像这样:
enter image description here

问题:
但是当我尝试根据P2的ParentId访问P3时,我收到一个错误。

  

[无法绑定多部分标识符“a1.ParentId”。]

根据以下查询:
select a.Title as P1 , (select a1.Title from AdjT as a1 where a1.Id=a.ParentId) as P2 , (select a2.Title from AdjT as a2 where a2.Id=a1.ParentId) as P3 --"a1.ParentId" ERROR from Adjt as a where a.TypeM='AAA' and a.Id=4;
即使我写为P2.ParentId,它也会给我:

  

无法绑定多部分标识符“P2.ParentId”。

我该怎么做才能让它发挥作用?

我目前使用的解决方法
我正在使用嵌套查询来获取我需要的数据和层次结构 使用以下查询完成:
select a.Title as P1 , (select a1.Title from AdjT as a1 where a1.Id=a.ParentId) as P2 , (select a2.Title from AdjT as a2 where a2.Id=(select a1.ParentId from AdjT as a1 where a1.Id=a.ParentId)) as P3 , (select a3.Title from AdjT as a3 where a3.Id=(select a2.ParentId from AdjT as a2 where a2.Id=(select a1.ParentId from AdjT as a1 where a1.Id=a.ParentId))) as P4 from Adjt as a where a.TypeM='AAA' and a.Id=4;
有没有更好的方法呢?为什么我只能访问第一列的parentId?
我无法编辑表的架构或数据的存储方式。必须使用叶节点的Id从下到上获取层次结构。如上所示。
我尝试使用CTE获取分层数据,但我希望它为“列”而不是“行”。将这些CTE行转换为“代码”中的列也不是一种选择。
如果任何人可以提出更好的方法来做到这一点,那将是最有帮助的。

感谢您阅读我的问题,我们将不胜感激。

2 个答案:

答案 0 :(得分:2)

你想做一个像

这样的自我加入
select 
a.Title as P1
a1.Title as Tital1,
a2.Title as title2

from AdjT a 
join AdjT a1 on a1.Id=a.ParentId
join AdjT a2 on a2.Id=a1.ParentId
where a.TypeM = 'AAA'
and a.Id = 4;

答案 1 :(得分:1)

实现这一目标需要几种技术。

首先是自我加入。实际上,自联接允许您将行转换为列。通过以此样式展平您的数据,您可以并排查看父级和子级。

接下来我们需要一个OUTER JOIN。因为您想从任何级别进行搜索,所以不会总是有3个父级(例如Id 2只有一个父级)。如果没有父项,则正常连接将过滤掉记录。当没有匹配的记录时,外连接通过返回NULL来避免这种情况。

我已在表VARIABLE中重新创建了您的示例数据。这样可以更轻松地共享示例代码。

样本数据

/* Table VAR creates sample records we can 
 * all share.
 */
DECLARE @Sample TABLE
    (
        Id            INT PRIMARY KEY,
        ParentId    INT,
        Title        VARCHAR(50),
        TypeM        VARCHAR(3)
    )
;

/* Populate sample data.
 */
INSERT INTO @Sample
    (
        Id,
        ParentId,
        Title,
        TypeM
    )
VALUES
    (1, 0, 'Parent 1 - [P1]', 'AAA'),
    (2, 1, 'Child 1 - [C1] P1', 'AAA'),
    (3, 2, 'Child 2 - [C2] C1 P1', 'AAA'),
    (4, 3, 'Child 3 - [C3] C2 C1 P1', 'AAA'),
    (5, 0, 'Parent 1 - [P2]', 'DDD'),
    (6, 5, 'Child 1 - [C1] P2', 'DDD'),
    (7, 6, 'Child 2 - [C2] C1 P2', 'DDD'),
    (8, 7, 'Child 3 - [C3] C2 C1 P2', 'DDD')
;

实施例

/* Self joins can extract the hierarchy.
 * Outer joins ensure results are always returned.
 */
SELECT
    s1.Title AS [P1],
    s2.Title AS [P2],
    s3.Title AS [P3],
    s4.Title AS [P4]
FROM
    @Sample AS s1
        LEFT OUTER JOIN @Sample AS s2        ON s2.Id = s1.ParentId
        LEFT OUTER JOIN @Sample AS s3        ON s3.Id = s2.ParentId
        LEFT OUTER JOIN @Sample AS s4        ON s4.Id = s3.ParentId
WHERE
    s1.Id = 4
;

尝试将WHERE id = 4替换为3以查看外部联接的实际效果。