-2

Ich habe zwei Tabellen, TableA und TableB. TableB hat eine FK zu TableA. Dies ist eine SQL Server 2012-Datenbank mit Primärschlüsseln in beiden Tabellen mit der Bezeichnung Id.. Es sind noch keine anderen Indizes vorhanden.TSQL-Abfrage Von SQL Server 2012-Datenbank, zwei verschiedene Tabellen, ein Elternteil, ein Kind

Die erste Tabelle als TableA hält, den Zugriff auf einen Ordner mit den folgenden Spalten:

  • Id (RowId, Primärschlüssel)
  • Path (vollständiger Pfad des Ordner/Verzeichnisses, nvarchar (255)
  • )
  • GroupName (Active Directory-Gruppe, nvarchar (255))
  • Guid (Guid der Gruppe, nvarchar (128))

Die zweite Tabelle als TableB hält Berechtigungen für diesen Ordner oder Verzeichnis:

  • Id (RowId, Primary Key)
  • TableARowId (FK, RowId von TableA)
  • Permission (nvarchar (128) , 12 verschiedene mögliche Werte)

Was ich gefragt habe zu tun ist, Path abzufragen, GroupName, Guid und Permissions für alle Ordner. Keine große Sache.

Das Problem ist, wenn die Gruppen und Berechtigungen von einem bestimmten Ordner in dem Pfad (Beispiel: \\FolderA\FolderB\FolderC\) ist das gleiche der ganzen Weg hinunter auf den niedrigsten Stand (\\FolderA\FolderB\FolderC\ .... \Folder[N]), sie wollen nur sehen, nach oben in den ersten Ordner mit den gleichen Gruppen und Berechtigungen. Wenn also FolderB andere Gruppen und Berechtigungen als FolderA hat, dann sind alle benötigten Felder im Datensatz für diesen Pfad enthalten. Wenn FolderC über andere Gruppen und Berechtigungen als FolderB verfügt, befinden sich alle erforderlichen Felder im Dataset für diesen Pfad.

Aber wenn FolderC die gleiche Anzahl von Gruppen hat und Berechtigungen den ganzen Weg hinunter zu FolderW, dann der letzte Ordner in dem Datensatz für diesen Pfad FolderC sein wird. Das ist der Teil, den ich nicht verstehen kann.

Ich vermutete, die Antwort sollte eine rekursive CTE mit dem Anker als Root-Verzeichnis enthalten. Aber ich dachte, die Rekursion sollte die Gruppen und Berechtigungen des letzten Ordners mit dem vorherigen Datensatz vergleichen, und wenn es anders ist, füge es dem Datensatz hinzu, andernfalls überspringe es.

Aber es gibt etwas, das ich nicht durchmachen konnte, während ich versuchte, meine erste Frage zu beantworten. Wie codierst du das Szenario von FolderA - FolderC ist anders, dann ist FolderC zu FolderP identisch, und FolderP zu FolderZ sind anders? In diesem Fall möchte ich trotzdem alle Ordner bis zu FolderP anzeigen lassen. Das ist der Teil, der meinen Kopf schmerzt.

Der Code, den ich schrieb, brachte mich nicht sehr weit.Ich schrieb:

 (SELECT 
      [Path] 
      ,[GroupName] 
      ,[Guid] 
      ,PermissionAsOneRow 
     FROM [TableA] TA INNER JOIN 
      ( SELECT [TableARowId], PermissionAsOneRow FROM (
      SELECT [Id], TBL1.[TableARowId], 
       (SELECT [Permission] + ', ' 
        FROM [TableB] TBL2 
        WHERE TBL2.[TableARowId] = TBL1.[TableARowId] 
        FOR XML PATH('')) AS PermissionAsOneRow 
       FROM [TableB] TBL1 
       GROUP BY [Id], TBL1.[TableARowId]) AS MYDATA 
     GROUP BY [TableARowId], PermissionAsOneRow) AS MD ON TA.Id = MD.[TableARowId]) 

Das ist mir Daten gibt, die wie folgt aussehen:

 Id   Path         GroupName   Guid       Permission 
----------------------------------------------------------------------------------------------------------------------- 
1   \\FolderA\FolderB\       SomeGroupNameA  [RandomGuidValueHereA]   PermissionA,PermissionB,PermissionC,PermissionD 
2   \\FolderA\FolderB\FolderC\     SomeGroupNameB  [RandomGuidValueHereB]   PermissionA,PermissionB,PermissionC,PermissionD 
3   \\FolderA\FolderB\FolderC\...Folder[N]  SomeGroupNameC  [RandomGuidValueHereC]   PermissionA,PermissionB,PermissionC 

ich die Daten auf diese Weise organisiert, weil ich dachte, es wäre leicht, rudert auf dem Berechtigungsfeld nach Zeile zu vergleichen, wie ich wie oben beschrieben, unter Verwendung des rekursiven CTE. Aber ehrlich gesagt wusste ich nicht, wie ich den nächsten Schritt machen sollte und fing an zu denken, dass es nicht funktionieren würde.

Alle und alle Hilfe wird geschätzt.

Für diejenigen, die antworten können, bitte erklären, damit ich daraus lernen kann.

unten Siehe zum Beispiel von Daten, bitte meine Formatierung

Beispiel von Daten in TableA

Id   Path           GroupName  Guid 
------------------------------------------------------------------------------------ 
1   \\FolderA\FolderB\       SomeGroupNameA  [RandomGuidValueHereA] 
2   \\FolderA\FolderB\FolderC\     SomeGroupNameB  [RandomGuidValueHereB] 
3   \\FolderA\FolderB\FolderC\...Folder[N]  SomeGroupNameC  [RandomGuidValueHereC] 
4   \\FolderAA\FolderBB\FolderCC\    SomeGroupNameD  [RandomGuidValueHereD] 
5   \\FolderAA\FolderBB\FolderCC\...Folder[N] SomeGroupNameE  [RandomGuidValueHereE] 

Beispiel von Daten in TableB

Id   TableARowId Permission 
-------------------------- 
1    1   PermissionA 
2    1   PermissionB 
3    1   PermissionC 
4    1   PermissionD 
5    2   PermissionA 
6    2   PermissionB 
7    2   PermissionC 
+0

Sie können Ihre Beispieldaten mit '{}' Codeblöcken formatieren und sie anders darstellen (wie bei Datenbanken). Ziehen Sie auch in Erwägung, Ihren Ansatz hinzuzufügen - Abfrage, die Sie versucht haben. –

+0

Ich habe die Beispieldaten @ConsiderMe aktualisiert, Danke. –

+0

Sie sollten die Beispieldaten wirklich als ** Tabellen ** formatiert anzeigen - viel einfacher zu lesen und zu verstehen! –

Antwort

0

Ich bin immer noch ein wenig perplex entschuldigen mit dem, was Sie wollen, aber es kann etwas von Nutzen sein in diesem:

-- Sample data. 
declare @Folders as Table (FolderId Int Identity, Folder VarChar(16)); 
insert into @Folders (Folder) values 
    ('\\A0\'), ('\\A0\A1\'), ('\\A0\A1\A2\'), ('\\A0\A1\A2\A3\'), 
    ('\\B0\'), ('\\B0\B1\'), ('\\B0\B1\B2\'), ('\\B0\B1\B2\B3\'), 
    ('\\C0\'), ('\\C0\C1\'), ('\\C0\C1\C2\'), ('\\C0\C1\C2\C3\'), 
    ('\\D0\'), ('\\D0\D1\'), ('\\D0\D1\D2\'), ('\\D0\D1\D2\D3\'); 

declare @Permissions as Table (PermissionId Int Identity, Permission VarChar(32)); 
insert into @Permissions (Permission) values 
    ('Create'), ('Delete'), ('Read'), ('Write'), ('Corrupt'); 

select * from @Folders; 
select * from @Permissions; 

-- It is assumed that all root folders have permissions explicitly specified. 
declare @FolderPermissions as Table (FolderId Int, PermissionId Int); 
insert into @FolderPermissions (FolderId, PermissionId) values 
    (1, 3), (1, 4), 
    (3, 3), (3, 4), 
    (5, 3), (5, 4), 
    (6, 3), (6, 4), (6, 1), (6, 2), 
    (9, 3), (9, 4), (9, 1), (9, 2), 
    (11, 3), (11, 4), 
    (13, 1), (13, 2), 
    (14, 3), (14, 4), 
    (16, 5); 

-- Dump the sample data. 
select Folder, 
    Stuff((select ',' + Permission from @Permissions as P inner join @FolderPermissions as FP on FP.PermissionId = P.PermissionId where FP.FolderId = F.FolderId order by P.PermissionId asc for XML path(''), type).value('.[1]', 'VarChar(max)'), 1, 1, '') as Permissions 
    from @Folders as F 
    order by Folder; 

-- Generate a folder tree with inherited permissions. 
with FoldersWithDepths as (
    -- Depth is zero for root folders, 1 for children of roots, ... . 
    select FolderId, Folder, Len(Folder) - Len(Replace(Folder, '\', '')) - 3 as Depth, 
    Stuff((select ',' + Permission from @Permissions as P inner join @FolderPermissions as FP on FP.PermissionId = P.PermissionId where FP.FolderId = F.FolderId order by P.PermissionId asc for XML path(''), type).value('.[1]', 'VarChar(max)'), 1, 1, '') as Permissions 
    from @Folders as F), 
    FolderTree as (
    -- Start with root folders. 
    select FolderId, Folder, Depth, Permissions, Cast(1 as Bit) as PermissionsChanged, Cast(NULL as Int) as ParentFolderId 
     from FoldersWithDepths 
     where Depth = 0 
    union all 
    -- Add children on the way down while inheriting permissions from their parents if no permissions are explicitly specified. 
    select Child.FolderId, Child.Folder, Child.Depth, Coalesce(Child.Permissions, Parent.Permissions), 
     Cast(case when Coalesce(Child.Permissions, Parent.Permissions) = Parent.Permissions then 0 else 1 end as Bit), Parent.FolderId 
     from FolderTree as Parent inner join 
     FoldersWithDepths as Child on Child.Depth = Parent.Depth + 1 and Child.Folder like Parent.Folder + '_%\') 
    select FolderId, Depth, ParentFolderId, Replicate(' ', Depth * 2) + Folder as Folder, 
    PermissionsChanged, Permissions 
    from FolderTree 
-- where PermissionsChanged = 1 -- Controls whether all folders are shown or only those which have permissions not matching their parents'. 
    order by FolderTree.Folder; 

Debugging/Verständnis Hilfe: Sie können die endgültige select zu select * from FoldersWithDepths ändern, um die Zwischenergebnisse zu sehen.

+0

Wow. Danke @HABO, ich habe mir den Code für die letzten 10 Minuten angeschaut. Ich bin überrascht, dass ein CTE das schaffen kann. Ich kann es kaum erwarten, eine Chance zu bekommen. Ich schätze Ihre Hilfe sehr. –

+0

@JasonR. War das die Antwort? – HABO

+0

Ich konnte es auf diese Weise nicht herausfinden. Dies war eine Tabelle, die von einem SSI-Job aus einem C# -Skript befüllt wurde.Es gab bereits ein Skript, das alle Unterschiede in eine Tabelle einfügte, die die Quellentabelle für diese Frage darstellt. Ich schrieb ein zweites Skript, das eine zweite Tabelle mit den Ergebnissen füllte, nach denen ich suchte. Als ich durch die Ordner aufzählte, wenn es einen Unterschied von dem einen Ordner zu seinem Unterordner gab, habe ich alles eingefügt, was ich wissen wollte. Wenn nicht, übersprang ich den Einsatz, bis es da war. Das hat mir das gebracht, wonach ich gesucht habe. Ich würde es trotzdem gerne in Zukunft versuchen. –

Verwandte Themen