2016-08-03 11 views
0

Ich habe 2 Tabellen - Importieren und Vorlage und die Vorlage Tabelle hat 3 Kategorien Ebenen. Ich muss Kategorien von Import zu Vorlage einfügen, aber Import hat nur eine Spalte.Fügen Sie Kategorien und Unterkategorien aus einer anderen Tabelle ein

sql tables

Von pic, sollte es nur 5 Kategorien eingefügt werden, da gibt es 5 verschiedene diejenigen. Es gibt 2 Sub1-Kategorien und 1 Sub2-Kategorien. CSD_ID in der Template-Tabelle wird automatisch generiert. Die INSERT-Anweisung sollte die Primary_Cat_Id mit ihrer übergeordneten CSD_ID aktualisieren.

Beispiel, WC ist ein sub2 von zu Hause so sollte es die CSD_ID von Inlands- und bevölkert im Primary_Cat_Id aber es ist auch ein sub1 Bath erhalten, so sollte es die CSD_ID von Bath bekommen und es in PARENT_ID zu füllen.

Last_Lev ist entweder 1 oder 0 1 bedeutet dies die letzte Ebene ist und 0 bedeutet, es gibt eine Unterkategorie darunter

+0

Entschuldigung, Parent_ID für Bath sollte 1 – Jay

+0

sein, also ist die Schablonentabelle jetzt leer und Sie möchten sie mit bestimmten Werten füllen? Wenn dies der Fall ist, müssten Sie wahrscheinlich einen After-Insert-Trigger ausführen, um die CSD_ID/Category der Einfügung abzurufen und sie mit der Importtabelle zu vergleichen. Aktualisieren Sie dann parent_id, primary_cat_id, last_lev entsprechend. – ZLK

Antwort

1

Eine Möglichkeit, dies durch die Schaffung eines AFTER INSERT Trigger auf der Template-Tabelle ist tun könnte, so dass Beim Einfügen aus der Import-Tabelle werden die Werte für Parent_Id, Lev_No, Primary_Cat_Id und Last_Lev automatisch aktualisiert.

Ich gehe davon aus Ihrer Tabellenstrukturen etwa wie folgt aussehen:

IF OBJECT_ID('Import', 'U') IS NOT NULL DROP TABLE Import; 

CREATE TABLE Import (
     [Main Category] VARCHAR(255) -- NOT NULL? 
    , [Sub Category 1] VARCHAR(255) 
    , [Sub Category 2] VARCHAR(255)); 

INSERT Import 
VALUES ('Domestic', NULL, NULL) 
    , ('Domestic', 'House', NULL) 
    , ('Domestic', NULL, NULL) 
    , ('Domestic', NULL, NULL) 
    , ('Domestic', 'Bath', 'Toilet') 
    , ('Domestic', NULL, NULL) 
    , ('Commercial', NULL, NULL) 
    , ('Commercial', NULL, NULL) 
    , ('Commercial', NULL, NULL) 
    , ('Commercial', NULL, NULL) 
    , ('Commercial', NULL, NULL) 
    , ('Commercial', NULL, NULL); 

IF OBJECT_ID('Template', 'U') IS NOT NULL DROP TABLE Template; 

CREATE TABLE Template (
     CSD_ID INT IDENTITY (1, 1) PRIMARY KEY 
    , Category VARCHAR(255) NOT NULL 
    , Parent_Id INT 
    , Lev_No INT 
    , Primary_Cat_Id INT 
    , Last_Lev BIT); 

Ihre Trigger so etwas wie das aussehen sollte folgende:

IF OBJECT_ID('tr_Template_Insert', 'TR') IS NOT NULL DROP TRIGGER tr_Template_Insert; 
GO 

CREATE TRIGGER tr_Template_Insert 
ON Template 
AFTER INSERT 
AS BEGIN 
    WITH CTE AS (
     SELECT RN, cats, lvl 
     FROM (
      SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN 
      FROM Import) T 
     CROSS APPLY (
      VALUES ([Main Category], 1) 
       , ([Sub Category 1], 2) 
       , ([Sub Category 2], 3)) S(cats,lvl) 
     WHERE S.cats IS NOT NULL 
     ) 
    UPDATE T 
    SET Last_Lev = Z.lastLev 
     , Primary_Cat_Id = COALESCE(Z.PrimaryCat, T.CSD_ID) 
     , Parent_Id = COALESCE(Z.ParentCat, T.CSD_ID) 
     , Lev_No = Z.levNo 
    FROM Template T 
    JOIN (
     SELECT C.cats 
      , MAX(CASE WHEN C.lvl = LL.lastlev THEN 1 ELSE 0 END) lastLev 
      , MAX(Pri.primarycat) PrimaryCat 
      , MAX(Par.parentcat) ParentCat 
      , MAX(lvl) levNo 
     FROM CTE C 
     JOIN inserted I ON I.Category = C.cats 
     OUTER APPLY (
      SELECT T.CSD_ID 
      FROM CTE CZ 
      JOIN Template T ON T.Category = CZ.cats 
      WHERE CZ.RN = C.RN 
      AND CZ.lvl = 1) Pri(primarycat) 
     OUTER APPLY (
      SELECT T.CSD_ID 
      FROM CTE CZ 
      JOIN Template T ON T.Category = CZ.cats 
      WHERE CZ.RN = C.RN 
      AND CZ.lvl = C.lvl-1) Par(parentcat) 
     OUTER APPLY (
      SELECT MAX(lvl) 
      FROM CTE CZ 
      WHERE CZ.RN = C.RN) LL(lastlev) 
     GROUP BY C.cats) Z ON Z.cats = T.Category; 
END 

Es könnte ein einfacher Weg, dies zu tun, aber das funktioniert technisch (zumindest mit den Beispieldaten).

Danach würden Sie nur einen Cursor oder etwas brauchen, um die Einsätze nacheinander zu tun, mit den Hauptkategorien Start:

DECLARE @cats VARCHAR(255); 

DECLARE curs CURSOR FOR 
    SELECT cats 
    FROM (
     SELECT *, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN 
     FROM Import) Z 
    CROSS APPLY (
     VALUES ([Main Category], 1) 
      , ([Sub Category 1], 2) 
      , ([Sub Category 2], 3)) S(cats,lvl) 
    LEFT JOIN Template T ON T.Category = S.cats 
    WHERE S.cats IS NOT NULL 
    AND T.Category IS NULL 
    GROUP BY cats 
    ORDER BY MIN(lvl); -- main cats first, then subcat1, then subcat2 

OPEN curs; 
FETCH NEXT FROM curs INTO @cats; 
WHILE @@FETCH_STATUS = 0 BEGIN 
    INSERT Template(Category) 
    VALUES (@cats); 
    FETCH NEXT FROM curs INTO @cats; 
END 
CLOSE curs; 
DEALLOCATE curs; 

Der Cursor Hauptkategorie einfügen, dann Unterkategorie 1, dann Unterkategorie 2 und der Trigger füllen die restlichen Werte aus.

+0

Vielen Dank. Wäre es einfacher, wenn ich eine Merge-Funktion verwende? Mir wurde geraten, einen Merge zu betrachten, um den Einsatz und nach dem Einfügen zu tun. – Jay

+0

@Jay könnte man es natürlich manuell machen (oder, sagen wir, eine Spalte nach der anderen, beginnend mit den Hauptkategorien, dann in die Unterkategorie 1 und dann in die Unterkategorie 2). Ich denke, das würde drei Sätze von Einsätzen erfordern. Die grundlegende Logik wäre jedoch ähnlich. Sie müssten die Tabellen vergleichen und die Elternkatze, die Primärkatzen-ID und die letzte Stufe finden. – ZLK

Verwandte Themen