SQL 自加入状态获胜者查询
SQL Self Join Status Winner query
我有一个客户 table 有一个自连接 (Parent - Child),我需要写一个查询 returns child customer/s 其中 Status 允许 parent 或 child 下订单。该列是一个位列并且可以为空。
返回的结果将基于以下矩阵:
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)
根据事实 table,CASE WHEN 如下所示。
该示例使用 table 变量仅用于演示。
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);
您可以使用递归 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')
我试图回答我自己的问题...如果我只return寻找被允许下订单的儿童客户,那么以下问题有什么问题:
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)
我有一个客户 table 有一个自连接 (Parent - Child),我需要写一个查询 returns child customer/s 其中 Status 允许 parent 或 child 下订单。该列是一个位列并且可以为空。
返回的结果将基于以下矩阵:
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)
根据事实 table,CASE WHEN 如下所示。
该示例使用 table 变量仅用于演示。
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);
您可以使用递归 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')
我试图回答我自己的问题...如果我只return寻找被允许下订单的儿童客户,那么以下问题有什么问题:
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)