同一个表中的父子关系

oba*_*sta 5 join sql-server hierarchy

我有一个存储父/子记录的表,如下所示:

+-------+------------+---------+---------+------------+-----------+
|custid | custname   | deptid  | company |parentcustid| enrolled  |
+=======+============+=========+=========+============+===========+
| 7060  | Sally      |   AB1   | comp1   |  null      |     1     |
| 6953  | Ajit       |   AB7   | comp2   |  7060      |     1     |
| 6957  | Rahul      |   DE1   | comp3   |  7060      |     1     |
| 6958  | uday       |   TG6   | comp4   |  7060      |     1     |
| 6959  | john       |   HY7   | comp5   |  7060      |     1     |
| 6960  | netaji     |   HY5   | comp6   |  7060      |     1     |
| 6961  | prakriti   |   GT6   | comp7   |  7060      |     1     |
| 6962  | sachin     |   KL7   | comp8   |  7060      |     0     |
| 6963  | santosh    |   KK5   | comp9   |  7060      |     1     |
| 6964  | Ravi       |   PP0   | comp10  |  7060      |     1     |
+-------+------------+---------+---------+------------+-----------+
Run Code Online (Sandbox Code Playgroud)

是否可以返回已登记父记录而未登记相关子记录的记录?

这将返回我对 1 个特定客户的需求:

select a.custid, a.custname, a.deptid, a.company, a.parentcustid, a.enrolled
from customer a
where a.company = 'comp1' and a.Enrolled = 1
union all
select a.custid, a.custname, a.deptid, a.company, a.parentcustid, a.enrolled
from customer a
where a.parentcustid= 7060 and b.Enrolled = 0

+-------+------------+---------+---------+------------+-----------+
|custid | custname   | deptid  | company |parentcustid| enrolled  |
+=======+============+=========+=========+============+===========+
| 7060  | Sally      |   AB1   | comp1   |  null      |     1     |
| 6962  | sachin     |   KL7   | comp8   |  7060      |     0     |
+-------+------------+---------+---------+------------+-----------+
Run Code Online (Sandbox Code Playgroud)

如何构造查询以返回表中所有父子记录的该类型的结果集?

Eri*_*ing 7

在 SQL Server 中执行此操作的常用方法是使用递归 CTE

这是您的测试数据作为插入:

CREATE TABLE #yourmom
(
    custid INT,
    custname VARCHAR(10),
    deptid VARCHAR(3),
    company VARCHAR(10),
    parentcustid INT,
    enrolled BIT
)

INSERT #yourmom ( custid, custname, deptid, company, parentcustid, enrolled )
SELECT x.custid, x.custname, x.deptid, x.company, x.parentcustid, x.enrolled
FROM   ( VALUES ( 7060, 'Sally   ', 'AB1', 'comp1 ', NULL, 1 ),
                ( 6953, 'Ajit    ', 'AB7', 'comp2 ', 7060, 1 ),
                ( 6957, 'Rahul   ', 'DE1', 'comp3 ', 7060, 1 ),
                ( 6958, 'uday    ', 'TG6', 'comp4 ', 7060, 1 ),
                ( 6959, 'john    ', 'HY7', 'comp5 ', 7060, 1 ),
                ( 6960, 'netaji  ', 'HY5', 'comp6 ', 7060, 1 ),
                ( 6961, 'prakriti', 'GT6', 'comp7 ', 7060, 1 ),
                ( 6962, 'sachin  ', 'KL7', 'comp8 ', 7060, 0 ),
                ( 6963, 'santosh ', 'KK5', 'comp9 ', 7060, 1 ),
                ( 6964, 'Ravi    ', 'PP0', 'comp10', 7060, 1 )
        ) AS x ( custid, custname, deptid, company, parentcustid, enrolled );
Run Code Online (Sandbox Code Playgroud)

这是递归 CTE 查找它的方式:

WITH yourdad
AS ( SELECT y.custid, y.custname, y.deptid, y.company, y.parentcustid, y.enrolled
     FROM   #yourmom AS y
     WHERE  y.parentcustid IS NULL
            AND y.enrolled = 1
     UNION ALL
     SELECT ym2.custid, ym2.custname, ym2.deptid, ym2.company, ym2.parentcustid, ym2.enrolled
     FROM   yourdad AS yd
     JOIN   #yourmom AS ym2
     ON ym2.parentcustid = yd.custid
        AND ym2.enrolled = 0 )
SELECT *
FROM   yourdad;
Run Code Online (Sandbox Code Playgroud)

有一些关于它们的 Great Posts®:

希望这可以帮助!


Oli*_*bes 5

如果你只有一个级别的孩子,你可以加入表格

SELECT
    a.custid, a.custname, a.deptid, a.company,
    b.custid AS bcustid, b.custname AS bcustname, b.deptid AS bdeptid, b.company AS bcompany
FROM
    customer a
    LEFT JOIN customer b
        ON a.custid = b.parentcustid AND b.Enrolled = 0
WHERE
    a.parentcustid  IS NULL AND a.Enrolled = 1
Run Code Online (Sandbox Code Playgroud)

像这样,您不会丢失父记录和子记录之间的关系。

由于您知道父母已注册而孩子未注册,因此重新访问该enrolled列不会添加任何新信息。


如果要保留原始结果表形状,请使用附加列进行排序

SELECT
    custid, custname, deptid, company, parentcustid, enrolled,
    10 * custid AS orderKey
FROM customer
WHERE parentcustid IS NULL AND Enrolled = 1
UNION ALL
SELECT
    custid, custname, deptid, company, parentcustid, enrolled,
    10 * parentcustid + 1 AS orderKey
FROM customer
WHERE parentcustid IS NOT NULL AND Enrolled = 0
ORDER BY orderKey, custid
Run Code Online (Sandbox Code Playgroud)

请注意,此 ORDER BY 应用于整个联合,而不仅仅是第二个 SELECT。像这样,孩子总是列在他们父母的下面。

顺便说一句,将键乘以 2 就足以获得所需的顺序键效果。如果乘以 10,它只会显示得更好。如果您的客户 ID 始终最多为 4 位数字,您还可以将其10000 * custid用于父级和10000 * parentcustid + custid子级,并且仅通过orderKey排序来获得有序记录。