2016-08-03 61 views
0

我有2个表格 - 导入模板和模板表有3个级别的类别。我需要将类别从导入插入到模板,但导入只有一列。插入另一个表中的类别和子类别

sql tables

从PIC,它应该只插入5个类别,因为有5分明显的。有2个sub1类别和1个sub2类别。自动生成模板表格中的CSD_ID。 insert语句应该用其父父CSD_ID更新Primary_Cat_Id。

例如厕所是Domestic的sub2,所以它应该获得Domestic的CSD_ID并填充在Primary_Cat_Id中,但它也是Bath的sub1,所以它应该获得Bath的CSD_ID并将其填充到Parent_ID中。

Last_Lev是1或0。1意味着它是最后一个级别,0表示有子类别下面就可以做到这一点

+0

对不起,Bath的Parent_ID应该是1 – Jay

+0

,所以模板表现在是空的,你想用特定的值填充它吗?如果是这样,您可能需要在插入触发器后执行以获取插入的CSD_ID/Category并根据导入表进行检查,然后相应地更新parent_id,primary_cat_id和last_lev。 – ZLK

回答

1

一种方式是通过在模板表上创建AFTER INSERT触发,使得当您从导入表中插入时,它将自动更新Parent_Id,Lev_No,Primary_Cat_IdLast_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并且触发器将填充其余的值。

+0

谢谢。如果我使用合并功能会更容易吗?我被建议看看合并做插入和插入后。 – Jay

+0

@Jay你肯定可以手动做(或者说,一次做一列,从主要类别开始,然后移到子类别1,然后子类别2)。我想这将需要三组插入。尽管如此,基本的逻辑将是相似的。你需要比较这些表格并找到父母猫,主要猫的身份证,不管它是否是最后一级。 – ZLK