2016-10-01 3 views
-1

J'ai une table client qui a une jointure automatique (Parent - Enfant), j'ai besoin d'écrire une requête qui renvoie le ou les clients enfants où le statut permet au parent ou à l'enfant de passer une commande . La colonne est une colonne bit et est nullable.Requête SQL Winner Status Winner

Les résultats retournés seraient basés sur la matrice suivante:

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 

comme demandé ici est schéma et script pour les données

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

S'il vous plaît, ajoutez un échantillon de données de la structure que vous avez. Qu'avez-vous essayé jusqu'à présent? – gofr1

+0

il n'y a pas suffisamment d'informations fournies pour aider. S'il vous plaît fournir d'autres exemples de données/schéma – Merenix

+0

excuses ajouté un schéma et quelques exemples de données - juste pensé que c'était un schéma assez simple, il semblait inutile de fournir un – Paul

Répondre

1

Basé sur la table de vérité, le cas quand car il serait être quelque chose comme ci-dessous.

L'exemple utilise une variable de table juste pour la démonstration.

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

Merci pour vous Réponse: Je l'ai tenté de répondre à ma propre queston ... ce serait mal avec la déclaration suivante ..select p.Customer_id \t, p.Name_desc \t, p.OrderIsAllowed_status comme Parent_IsAllowed \t, c. customer_id \t, c.ParentCustomer_id \t, c.Name_desc \t, c.OrderIsAllowed_status \t du client p jointure client c \t sur p.customer_id = c.ParentCustomer_id où \t (p.OrderIsAll owed_status est nulle et c.OrderIsAllowed_status = 1) ou \t (p.OrderIsAllowed_status = 1 et c.OrderIsAllowed_status est nulle) \t ou (p.OrderIsAllowed_status = 1 et c.OrderIsAllowed_status = 1) – Paul

+1

Si l'intention est que SQL avec pour obtenir seulement les enfants où [l'enfant est autorisé à commander] est vrai, alors que SQL n'est pas faux. Bien que personnellement avec une relation de plusieurs-à-un, je mettrais le "plusieurs" dans le et j'y joindrais le "un". – LukStorms

1

Vous pouvez utiliser CTE récursive:

;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 

sortie:

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 

J'ai utilisé cette table:

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

J'ai essayé de répondre à ma propre question ... qu'est-ce qui ne va pas avec t il suit ... si je cherchais à retourner seulement les clients enfants qui ont été autorisés à passer une commande:

+1

Cela ne fonctionnera pas si vous avez 'grandparent - parent - child'. – gofr1

+0

Merci - J'ai manqué ce scénario .. l'utilisation historique de la table dans mon cas a seulement un niveau de hiérarchie - parent - enfant, mais vous avez raison, je dois considérer le design original – Paul

+0

Mon plaisir! :) – gofr1