一种方式是通过在模板表上创建AFTER INSERT
触发,使得当您从导入表中插入时,它将自动更新Parent_Id
,Lev_No
,Primary_Cat_Id
和Last_Lev
的值。
我假设你的表结构是这个样子:
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);
你触发看起来应该像下面这样:
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
有可能做到这一点更简单的方法,但这在技术上是有效的(至少在样本数据方面)。
在此之后,你只需要一个鼠标或东西一一做刀片,先从主要类别:
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;
光标将插入主类别,然后子类1,然后子类别2并且触发器将填充其余的值。
对不起,Bath的Parent_ID应该是1 – Jay
,所以模板表现在是空的,你想用特定的值填充它吗?如果是这样,您可能需要在插入触发器后执行以获取插入的CSD_ID/Category并根据导入表进行检查,然后相应地更新parent_id,primary_cat_id和last_lev。 – ZLK