2016-10-01 5 views
-1

У меня есть таблица клиентов, которая имеет самостоятельное присоединение (родительский - дочерний), мне нужно написать запрос, который возвращает дочерних клиентов, где статус Позволяет родительскому или дочернему лицу разместить заказ , Столбец является столбцом бит и имеет значение NULL.SQL Self Join Status Winner query

Возвращаемые результаты будут основаны на следующей матрице:

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) 
+0

Пожалуйста, добавьте образец данных структуры, которую у вас есть. что ты уже испробовал? – gofr1

+0

информации для оказания помощи недостаточно. Просьба представить дополнительные примеры данных/схемы – Merenix

+0

извинения добавили схему и некоторые данные примера - просто подумали, что это была простая схема, для которой не нужно было указывать – Paul

ответ

1

на основе таблицы истинности, в случае, когда для этого будет что-то вроде ниже.

В примере используется переменная таблицы только для демонстрации.

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); 
+0

Спасибо за вас ответить: я попытался ответить на мой собственный Queston ... что было бы неправильно со следующим утверждением ..select p.Customer_id \t, p.Name_desc \t, p.OrderIsAllowed_status как Parent_IsAllowed \t, гр. CUSTOMER_ID \t, c.ParentCustomer_id \t, c.Name_desc \t, c.OrderIsAllowed_status \t от клиента р внутреннее соединение клиента гр \t на p.customer_id = c.ParentCustomer_id где \t (p.OrderIsAll owed_status равно нулю и c.OrderIsAllowed_status = 1) \t или (p.OrderIsAllowed_status = 1 и c.OrderIsAllowed_status равно нулю) \t или (p.OrderIsAllowed_status = 1 и c.OrderIsAllowed_status = 1) – Paul

+1

Если намерение с этим SQL является для получения только тех детей, где [Ребенок разрешен к заказу] истинно, тогда этот SQL не ошибается. Хотя лично с отношением «много-к-одному» я бы поставил «много» в «от» и присоединился к «одному» к нему. – LukStorms

1

Вы можете использовать рекурсивное ОТВ:

;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') 
0

Я попытался ответить на мой собственный вопрос ... что было бы неправильно с t он следовал за ... если бы я хотел вернуть только детей-клиентов, которым было разрешено сделать заказ:

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

Это не сработает, если у вас есть «grandparent - parent - child». – gofr1

+0

Спасибо - я пропустил этот сценарий .. историческое использование таблицы в моем случае имеет только один уровень иерархии - родительский - ребенок, но вы правы, мне нужно рассмотреть оригинальный дизайн – Paul

+0

Мое удовольствие! :) – gofr1