2016-08-03 42 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