简体   繁体   中英

SQL query to search for a record in one table and replace it with multiple records from another table

I have two tables - package and subpackage as:

CREATE TABLE Package (
    Sequence int PRIMARY KEY,
    Package int,
    Mnemonic char(3),
    MnemonicValue int
);

CREATE TABLE SubPackage (
    Sequence int PRIMARY KEY,
    SubPackage int,
    Mnemonic char(3),
    MnemonicValue int
);

INSERT INTO Package (Sequence, Package, Mnemonic, MnemonicValue)
VALUES (1, 111, 'XXX', 0), (2, 111, 'SUB', 153), (3, 111, 'DDD', 30), (4, 111, 'YYY', 20), (5, 111, 'ZZZ', 1000);

INSERT INTO SubPackage (Sequence, SubPackage, Mnemonic, MnemonicValue)
VALUES (1, 153, 'AAA', 20), (2, 153, 'BBB', 1000), (3, 153, 'CCC', 30);

The requirement is to search for a Mnemonic 'SUB' in the package table and replace the SUB record with the records from 'Subpackage' table for the mapped Mnemonic Value (153) and resequence the sequence values as shown in the [Result][2] table.

I have tried using the update statement as:

UPDATE package
SET    Mnemonic = subpackage.Mnemonic
FROM   package
       INNER JOIN subpackage
       ON package.MnemonicValue = subpackage.SubPackage

But this replaces the SUB record from package table with only AAA record from subpackage table. I want SUB record to be replaced with all records from subpackage table and re-sequence it in a new table as shown in the Result table.

Desired result:

Sequence | Particular | Mnemonic | MnemonicValue

       1 |         111|       XXX|             0        
       2 |         111|       AAA|            20
       3 |         111|       BBB|          1000
       4 |         111|       CCC|            30
       5 |         111|       DDD|            30
       6 |         111|       YYY|            20
       7 |         111|       ZZZ|          1000

You can use a left join to get the results that you want:

select
    p.sequence,
    p.package,
    coalesce(s.mnemonic, p.mnemonic) mnemonic,
    coalesce(s.mnemonic_value, p.mnemonic_value) mnemonic_value
from package p
left join sub_package s 
    on  p.mnemonic = 'SUB'
    and p.mnemonic_value = s.sub_package

"Replacing" the new rows is a bit more complicated. It would probably be simpler to insert the new rows, then remove the original (you can do this in a transaction):

start transaction;

insert into package(sequence, package, mnemonic, mnemonic_value)
select
    p.sequence,
    p.package,
    coalesce(s.mnemonic, p.mnemonic),
    coalesce(s.mnemonic_value, p.mnemonic_value)
from package p
left join sub_package s 
    on  p.mnemonic = 'SUB'
    and p.mnemonic_value = s.sub_package;

delete from package where mnemonic = 'SUB';

commit;

I don't think you can update Package table to get exactly result that you want, ie problem is that in your example you reordering Sequence column.

Anyway, here is SQL script(based on answer by GMB) that will generate result that you want to get:

select
    ROW_NUMBER() OVER (ORDER BY p.Sequence) as Sequence,
    p.Package,
    coalesce(s.Mnemonic, p.Mnemonic) Mnemonic,
    coalesce(s.MnemonicValue, p.MnemonicValue) MnemonicValue
from Package p
left join SubPackage s 
    on p.MnemonicValue = s.SubPackage
order by p.Sequence

But, AFAIK it works only with MySQL 8

Here is a link to SQLFiddle , but beware it's for Postgres(as SQLFiddle doesn't support MySQL 8).

If you're using earlier version of MySQL, you can try to emulate row_number function

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM