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.
Entschuldigung, Parent_ID für Bath sollte 1 – Jay
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