【问题标题】:SQL Self Join Status Winner querySQL 自加入状态获胜者查询
【发布时间】:2016-10-01 10:22:04
【问题描述】:

我有一个具有自联接(父-子)的客户表,我需要编写一个查询来返回子客户,其中状态允许父或子下订单。该列是位列,可以为空。

返回的结果将基于以下矩阵:

parent_status   child_status    Child is allowed to Order
null                 null           FALSE
null                 0              FALSE
null                 1              TRUE
1                    null           TRUE
1                    1              TRUE
1                    0              FALSE
0                    null           FALSE
0                    1              FALSE
0                    0              FALSE

这里要求的是数据的架构和脚本

    CREATE TABLE [dbo].[Customer](
    [Customer_id] [int] NOT NULL,
    [ParentCustomer_id] [int] NULL,
    [Name_desc] [nvarchar](50) NULL,
    [OrderIsAllowed_status] [bit] NULL)
GO
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(1,null,'Parent 1',1)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(2,1,'Parent 1 - Child 1',null)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(3,1,'Parent 1 - Child 2',0)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(4,1,'Parent 1 - Child 3',1)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(5,null,'Parent 2',null)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(6,5,'Parent 2 - Child 1',null)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(7,5,'Parent 2 - Child 2',1)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(8,5,'Parent 2 - Child 3',0)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(9,null,'Parent 3',0)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(10,9,'Parent 3 - Child 1',null)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(11,9,'Parent 3 - Child 2',1)
insert Customer
([Customer_id],[ParentCustomer_id],[Name_desc] ,[OrderIsAllowed_status])
values(12,9,'Parent 3 - Child 3',0)

【问题讨论】:

  • 请添加您拥有的结构数据样本。到目前为止,您尝试过什么?
  • 提供的信息不足,无法提供帮助。请提供其他示例数据/架构
  • 道歉添加了一个架构和一些示例数据 - 只是认为这是一个足够简单的架构,看起来没有必要提供一个
  • 你的预期输出是什么?

标签: sql-server hierarchy self-join


【解决方案1】:

根据真值表,CASE WHEN 如下所示。

该示例使用表变量仅用于演示。

declare @Customer table (Customer_id int NOT NULL, ParentCustomer_id int, OrderIsAllowed_status bit);

insert @Customer ([Customer_id], [ParentCustomer_id], [OrderIsAllowed_status]) values
(1,null,1),
(2,1,null),
(3,1,0),
(4,1,1),
(5,null,null),
(6,5,null),
(7,5,1),
(8,5,0),
(9,null,0),
(10,9,null),
(11,9,1),
(12,9,0);

select 
child.Customer_id, 
child.ParentCustomer_id,
(case 
 when child.ParentCustomer_id is null then 'Parent '+ cast(child.Customer_id as varchar)
 else concat('Parent ',parent.Customer_id,' - Child ',child.Customer_id)
 end) as Name_desc,
parent.OrderIsAllowed_status as parent_status,
child.OrderIsAllowed_status as child_status,
cast(case 
     when child.OrderIsAllowed_status = 1 and parent.OrderIsAllowed_status = 1 then 1
     when child.OrderIsAllowed_status = 1 and parent.OrderIsAllowed_status is null then 1
     when child.OrderIsAllowed_status is null and parent.OrderIsAllowed_status = 1 then 1
     else 0 
     end as bit) as [Child is allowed to Order]
from @Customer child
left join @Customer parent on (child.ParentCustomer_id = parent.Customer_id);

【讨论】:

  • 感谢您的回答:我试图回答我自己的问题...以下语句有什么问题...选择 p.Customer_id ,p.Name_desc ,p.OrderIsAllowed_status as Parent_IsAllowed ,c .Customer_id ,c.ParentCustomer_id ,c.Name_desc ,c.OrderIsAllowed_status from Customer p 内部连接 ​​Customer c on p.customer_id = c.ParentCustomer_id 其中 (p.OrderIsAllowed_status 为空且 c.OrderIsAllowed_status =1) 或 (p.OrderIsAllowed_status = 1并且 c.OrderIsAllowed_status 为空)或(p.OrderIsAllowed_status = 1 和 c.OrderIsAllowed_status = 1)
  • 如果该 SQL 的目的是仅获取 [The child is allowed to order] 为 true 的那些 Children,那么该 SQL 没有错。虽然我个人是多对一的关系,但我会将“多”放入 from 并将“一”加入其中。
【解决方案2】:

您可以使用递归 CTE:

;WITH rec AS (
    SELECT  Customer_id,
            ParentCustomer_id,
            Name_desc,
            OrderIsAllowed_status,
            CAST(NULL AS bit) as parent_status,
            1 as [Level]
    FROM #Customer c
    WHERE ParentCustomer_id IS NULL
    UNION ALL
    SELECT  c.Customer_id,
            c.ParentCustomer_id,
            c.Name_desc,
            c.OrderIsAllowed_status,
            r.OrderIsAllowed_status,
            r.[Level]+ 1
    FROM rec r
    INNER JOIN #Customer c
        ON c.ParentCustomer_id = r.Customer_id
)

SELECT  r.Customer_id,
        r.ParentCustomer_id,
        r.Name_desc,
        r.OrderIsAllowed_status,
        rs.[Child is allowed to Order]
FROM rec r
INNER JOIN #rules rs
    ON COALESCE(r.[OrderIsAllowed_status],2) = COALESCE(rs.child_status,2)
        AND COALESCE(r.parent_status,2) = COALESCE(rs.parent_status,2)
WHERE r.ParentCustomer_id IS NOT NULL

输出:

Customer_id ParentCustomer_id   Name_desc           OrderIsAllowed_status   Child is allowed to Order
10          9                   Parent 3 - Child 1  NULL                    FALSE
11          9                   Parent 3 - Child 2  1                       FALSE
12          9                   Parent 3 - Child 3  0                       FALSE
6           5                   Parent 2 - Child 1  NULL                    FALSE
7           5                   Parent 2 - Child 2  1                       TRUE
8           5                   Parent 2 - Child 3  0                       FALSE
2           1                   Parent 1 - Child 1  NULL                    TRUE
3           1                   Parent 1 - Child 2  0                       FALSE
4           1                   Parent 1 - Child 3  1                       TRUE

我用过这个表:

CREATE TABLE #Customer (
    [Customer_id] [int] NOT NULL,
    [ParentCustomer_id] [int] NULL,
    [Name_desc] [nvarchar](50) NULL,
    [OrderIsAllowed_status] [bit] NULL
)

INSERT INTO #Customer VALUES
(1,null,'Parent 1',1),
(2,1,'Parent 1 - Child 1',null),
(3,1,'Parent 1 - Child 2',0),
(4,1,'Parent 1 - Child 3',1),
(5,null,'Parent 2',null),
(6,5,'Parent 2 - Child 1',null),
(7,5,'Parent 2 - Child 2',1),
(8,5,'Parent 2 - Child 3',0),
(9,null,'Parent 3',0),
(10,9,'Parent 3 - Child 1',null),
(11,9,'Parent 3 - Child 2',1),
(12,9,'Parent 3 - Child 3',0)

CREATE TABLE #rules (
    parent_status bit NULL,
    child_status bit NULL,
    [Child is allowed to Order] nvarchar(5) NULL
)

INSERT INTO #rules VALUES
(null, null, 'FALSE'),
(null, 0, 'FALSE'),
(null, 1, 'TRUE'),
(1, null, 'TRUE'),
(1, 1, 'TRUE'),
(1, 0, 'FALSE'),
(0, null, 'FALSE'),
(0, 1, 'FALSE'),
(0, 0, 'FALSE')

【讨论】:

    【解决方案3】:

    我已尝试回答我自己的问题...如果我只想退回允许下订单的儿童客户,那么以下问题会有什么问题:

     select p.Customer_id
        ,p.Name_desc
        ,p.OrderIsAllowed_status as Parent_IsAllowed
        ,c.Customer_id
        ,c.ParentCustomer_id
        ,c.Name_desc
        ,c.OrderIsAllowed_status    
    from Customer p
    inner join Customer c
        on p.customer_id = c.ParentCustomer_id
    where 
        (p.OrderIsAllowed_status is null and c.OrderIsAllowed_status =1)
        or(p.OrderIsAllowed_status = 1 and c.OrderIsAllowed_status is null)
        or (p.OrderIsAllowed_status = 1 and c.OrderIsAllowed_status = 1)
    

    【讨论】:

    • 如果你有grandparent - parent - child,这将不起作用。
    • 谢谢 - 我错过了这个场景..在我的案例中,表的历史用法只有一个层次结构 - 父 - 子,但你是对的我需要考虑原始设计
    • 我的荣幸! :)
    猜你喜欢
    • 2020-03-06
    • 1970-01-01
    • 2021-08-04
    • 2018-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-20
    • 1970-01-01
    相关资源
    最近更新 更多