I have a customer table that has a self join (Parent - Child), I need to write a query that returns the child customer/s where the Status Allows the parent or child to place an order. The column is a bit column and is nullable.
我有一个具有自联接的客户表(父 - 子),我需要编写一个查询,返回子客户,其中状态允许父母或子女下订单。该列是一个位列,可以为空。
The results returned would be based on the following matrix:
返回的结果将基于以下矩阵:
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
as requested here is schema and script for data
这里要求的是数据的模式和脚本
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)
3 个解决方案
#1
1
Based on the truth table, the CASE WHEN for it would be something like below.
基于真值表,CASE WHEN对于它将如下所示。
The example uses a table variable just for demonstration.
该示例使用表变量仅用于演示。
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);
#2
1
You can use recursive CTE:
您可以使用递归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
Output:
输出:
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
I have used this tables:
我用过这个表:
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
0
I have attempted to answer my own question...what would be wrong with the following ...if I was looking to return only the child customers that were allowed to place an order:
我试图回答我自己的问题......以下内容会出现什么问题...如果我想要只返回允许下订单的儿童客户:
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)
#1
1
Based on the truth table, the CASE WHEN for it would be something like below.
基于真值表,CASE WHEN对于它将如下所示。
The example uses a table variable just for demonstration.
该示例使用表变量仅用于演示。
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);
#2
1
You can use recursive CTE:
您可以使用递归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
Output:
输出:
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
I have used this tables:
我用过这个表:
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
0
I have attempted to answer my own question...what would be wrong with the following ...if I was looking to return only the child customers that were allowed to place an order:
我试图回答我自己的问题......以下内容会出现什么问题...如果我想要只返回允许下订单的儿童客户:
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)