Reputation: 333
I have tbl1
IDa | year | field2 |
----+------+---------
1 | 2015 | bbb |
2 | 2015 | aaa |
3 | 2015 | ccc |
---------------------
I'm using INSERT INTO SELECT
to copy all the data from 2015, but with change in year
into 2016
INSERT INTO tbl1 (year, field2) SELECT '2016', field2 from tbl1 WHERE year = '2015'
and return the data like this
IDa | year | field2 |
----+------+---------
1 | 2015 | bbb |
2 | 2015 | aaa |
3 | 2015 | ccc |
4 | 2016 | bbb |
5 | 2016 | aaa |
6 | 2016 | ccc |
---------------------
Now, I have another table tbl2
that have a foreign key to IDa
in tbl1
, which the relations is one to many like this
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 |
---------------------------
And now, with INSERT INTO SELECT
I also want to copy data from tbl2
in year
2015 and change it to 2016, but with IDa
in year
2016
I've tried this
INSERT INTO tbl2 (year, IDa, field3)
SELECT year, (SELECT IDa FROM tbl1 WHERE year = '2016'), field3
FROM tbl2
WHERE year = '2015'
But this query getting error because one field return multiple value at the time.
So, how to make the right query for this? I want the result is like this
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 |
---------------------------
Is it possible?
I'm appreciate all the answers, thanks for help.
Upvotes: 2
Views: 365
Reputation: 31812
Add column oIDa
(original ID) to tbl1
.
ALTER TABLE tbl1 ADD oIDa INT;
Copy data with the original ID, so you can use it later.
INSERT INTO tbl1 (year, field2, oIDa) SELECT '2016', field2, IDa from tbl1 WHERE year = '2015';
Now you have a column, that you can join on, to find the new generated IDa
value:
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;
Now you can remove the new column:
ALTER TABLE tbl1 DROP COLUMN oIDa;
Upvotes: 2
Reputation: 86735
As it stands your sub query doesn't return the IDa
for one row, but all of the values for the whole year. (This is a problem because you can't put all those values in one field in one row.)
To fix your exact syntax you need to "correlate" the sub query against the table you're reading from, so that you get only one result per row, for your IDa lookup...
Unfortunately, in your case, that gets very messy. You need to look up what the original IDa
was in table1, then look for the matching row in the same table but for the next year...
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'
That said, there is a simpler way, using joins...
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
EDIT
If field2
doesn't exist, you have the problem of not knowing which IDa
to pick in each case.
That leaves two options, as I see it:
- Use the approach from @PaulSpiegel
- Manually introduce a proxy
Personally, this is sounding more and more convoluted, and a basic redesign sounds like it's going to be beneficial.
If you're unable to re-design or use the method from @PaulSpiegel, there is an option...
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
This assumes the only fields in tbl1
are year
and IDa
. If you have other fields in tbl1
then they should be included in the ROW_NUMBER()
's ORDER BY
clause, to ensure that the rows appear in the same order in both years.
If this doesn't make sense to you, then you probably shouldn't use it. Instead re-design or use @PaulSpiegel's approach.
Upvotes: 2
Reputation: 145
I don't 100% understand your data - so I'm not sure if Field2 and Field3 will always be the same for each year. If it is then this should work:
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';
Upvotes: 0