2016-11-09 77 views
2

tbl1試圖從有兩個表插入選擇一對多關係

IDa | year | field2 | 
----+------+--------- 
1 | 2015 | bbb | 
2 | 2015 | aaa | 
3 | 2015 | ccc | 
--------------------- 

我使用INSERT INTO SELECT將所有的數據從2015年複製,但變化year到2016

INSERT INTO tbl1 (year, field2) SELECT '2016', field2 from tbl1 WHERE year = '2015' 

,並返回這樣

IDa | year | field2 | 
----+------+--------- 
1 | 2015 | bbb | 
2 | 2015 | aaa | 
3 | 2015 | ccc | 
4 | 2016 | bbb | 
5 | 2016 | aaa | 
6 | 2016 | ccc | 
--------------------- 

現在的數據,我有另一個表tbl2那些在tbl1的外鍵IDa,其關係是一對多這樣

IDb | year | IDa | field3 | 
----+------+-----+--------- 
1 | 2015 | 1 | ddd | 
2 | 2015 | 1 | eee | 
3 | 2015 | 2 | fff | 
4 | 2015 | 3 | ggg | 
5 | 2015 | 3 | hhh | 
6 | 2015 | 3 | iii | 
--------------------------- 

而現在,INSERT INTO SELECT我也想將數據從tbl2year 2015年將其複製並更改爲2016年,但在

我已經試過這

INSERT INTO tbl2 (year, IDa, field3) 
    SELECT year, (SELECT IDa FROM tbl1 WHERE year = '2016'), field3 
    FROM tbl2 
    WHERE year = '2015' 

但此查詢GE因爲一個字段在當時返回多個值。

那麼,如何爲此做出正確的查詢呢?我想要的結果是這樣的

IDb | year | IDa | field3 | 
----+------+-----+--------- 
1 | 2015 | 1 | ddd | 
2 | 2015 | 1 | eee | 
3 | 2015 | 2 | fff | 
4 | 2015 | 3 | ggg | 
5 | 2015 | 3 | hhh | 
6 | 2015 | 3 | iii | 
7 | 2016 | 4 | ddd | 
8 | 2016 | 4 | eee | 
9 | 2016 | 5 | fff | 
10 | 2016 | 6 | ggg | 
11 | 2016 | 6 | hhh | 
12 | 2016 | 6 | iii | 
--------------------------- 

這可能嗎?

我很感激所有的答案,謝謝你的幫助。

+0

你存儲年份爲人品? – jarlh

+0

使用tbl1中的臨時列來存儲原始主鍵。否則,您在複製數據時會丟失該信息。 –

+0

@jarlh不,其int int – JTR

回答

2

既然這樣你的子查詢不一行返回IDa,但所有的值全年。 (這是一個問題,因爲你不能把所有這些值在一個字段一行。)

要解決您的確切語法,你需要「關聯」對你是從讀表的子查詢,以便每行只能得到一個結果,以便您的IDa查找...

不幸的是,在您的情況下,這會變得非常混亂。你需要查看一下原來的IDa在表1,然後尋找在同一個表的匹配行,但明年...

INSERT INTO 
    tbl2 (
     year, 
     IDa, 
     field3 
    ) 
SELECT 
    year + 1, 
    (SELECT IDa 
     FROM tbl1 
     WHERE year = tbl2.year + 1 
     AND field2 = (SELECT field2 
         FROM tbl1 
         WHERE IDa = tbl2.IDa 
        ) 
    ), 
    field3 
FROM 
    tbl2 
WHERE 
    year = '2015' 

這就是說,有一個簡單的方法,用連接。 ..

INSERT INTO 
    tbl2 (
     year, 
     IDa, 
     field3 
    ) 
SELECT 
    newer.year, 
    newer.IDa, 
    tbl2.field3 
FROM 
    tbl2 
INNER JOIN 
    tbl1 older 
     ON older.IDa = tbl2.IDa 
INNER JOIN 
    tbl1 newer 
     ON newer.year = older.year + 1 
     AND newer.field2 = older.field2 
WHERE 
    tbl2.year = 2015 

編輯

如果field2不存在,你不知道的問題,這IDa到pi在每種情況下。

剩下兩個選擇,因爲我看到它:
- 從@PaulSpiegel
使用的方法 - 手動引入代理

個人而言,這聽起來是越來越錯綜複雜,以及重新設計的基本聽起來像這將是有益的。

如果您無法重新設計或使用來自@PaulSpiegel的方法,有一個選項...

INSERT INTO 
    tbl2 (
     year, 
     IDa, 
     field3 
    ) 
WITH 
    ordered_tbl1 
(
    SELECT 
     ROW_NUMBER() OVER (PARTITION BY year ORDER BY year) AS ordinal, 
     tbl1.* 
    FROM 
     tbl1 
) 
SELECT 
    newer.year, 
    newer.IDa, 
    tbl2.field3 
FROM 
    tbl2 
INNER JOIN 
    ordered_tbl1 older 
     ON older.IDa  = tbl2.IDa 
INNER JOIN 
    ordered_tbl1 newer 
     ON newer.year = older.year + 1 
     AND newer.ordinal = older.ordinal 
WHERE 
    tbl2.year = 2015 

這是假設在tbl1的字段只有yearIDa。如果您在tbl1中有其他字段,則應將它們包含在ROW_NUMBER()ORDER BY子句中,以確保這兩行在兩年內都以相同的順序出現。

如果這對你沒有意義,那麼你可能不應該使用它。相反,重新設計或使用@ PaulSpiegel的方法。

+0

'tbl1.IDa'是更新的還是更舊的? – JTR

+1

@JTR - 對不起,打字錯誤,但我本來希望你意識到這是'新的',因爲這是你要求的全部內容;)*(對不起,早期和特朗普的消息讓我感到脾氣和諷刺。)* – MatBailie

+0

這隻適用於'tbl1(year,field2)'是唯一的。 –

0

我不完全瞭解您的數據 - 所以我不確定Field2和Field3每年的情況是否會一直相同。如果是這樣,就可以:

INSERT INTO tbl2 (year, IDa, field3) 
SELECT c.Year, 
     c.Ida, 
     a.field3 
    FROM tbl2 a 
     INNER JOIN tbl1 b 
       ON a.IDa = b.Ida 
     INNER JOIN tbl1 c 
       ON field2 = field2 
       AND c.year = 2016 
WHERE a.year = '2015'; 
+0

yes,'field2'和'field3'每年的順序相同 – JTR

+0

我已經試過了您的查詢,但它沒有返回任何內容:( – JTR

+0

@JTR將'ON field2 = field2'這一行更改爲'ON c.field2 = b .field2' *(然後從'a','b'和'c'改變別名,使其更具可讀性;))* – MatBailie

2

oIDa(原始ID)添加到tbl1

ALTER TABLE tbl1 ADD oIDa INT; 

與原身份證複印資料,所以你以後可以使用它。

INSERT INTO tbl1 (year, field2, oIDa) SELECT '2016', field2, IDa from tbl1 WHERE year = '2015'; 

現在你有一個欄,你可以加入,即可找到所生成的新IDa值:

INSERT INTO tbl2 (year, IDa, field3) 
    SELECT year, tbl1.IDa, tbl2.field3 
    FROM tbl2 
    JOIN tbl1 ON tbl1.oIDa = tbl2.IDa 
    WHERE tbl2.year = 2015; 

現在你可以刪除新柱:

ALTER TABLE tbl1 DROP COLUMN oIDa; 
+0

uumm ...我很抱歉,但是,什麼是'INT UNSIGNED'又是什麼? – JTR

+0

'INT UNSIGNED'意味着只有正整數(從0到4,294,967,295)。但是你可以採用與'IDa'相同的數據類型。 –

+0

對不起,剛剛實現了sql-server標籤。我調整了代碼。 –