sql >> Database >  >> RDS >> PostgreSQL

Snelle query om te normaliseren op SQL-gegevens

Dit is mijn andere antwoord, uitgebreid tot drie kolommen:

        -- Some test data
CREATE TABLE the_table
        ( id SERIAL NOT NULL PRIMARY KEY
        , name varchar
        , a INTEGER
        , b varchar
        , c varchar
        );
INSERT INTO the_table(name, a,b,c) VALUES
 ( 'Chimpanzee' , 1, 'mammals', 'apes' )
,( 'Urang Utang' , 1, 'mammals', 'apes' )
,( 'Homo Sapiens' , 1, 'mammals', 'apes' )
,( 'Mouse' , 2, 'mammals', 'rodents' )
,( 'Rat' , 2, 'mammals', 'rodents' )
,( 'Cat' , 3, 'mammals', 'felix' )
,( 'Dog' , 3, 'mammals', 'canae' )
        ;

        -- [empty] table to contain the "squeezed out" domain {a,b,c}
CREATE TABLE abc_table
        ( id SERIAL NOT NULL PRIMARY KEY
        , a INTEGER
        , b varchar
        , c varchar
        , UNIQUE (a,b,c)
        );

        -- The original table needs a "link" to the new table
ALTER TABLE the_table
        ADD column abc_id INTEGER -- NOT NULL
        REFERENCES abc_table(id)
        ;
        -- FK constraints are helped a lot by a supportive index.
CREATE INDEX abc_table_fk ON the_table (abc_id);

        -- Chained query to:
        -- * populate the domain table
        -- * initialize the FK column in the original table
WITH ins AS (
        INSERT INTO abc_table(a,b,c)
        SELECT DISTINCT a,b,c
        FROM the_table a
        RETURNING *
        )
UPDATE the_table ani
SET abc_id = ins.id
FROM ins
WHERE ins.a = ani.a
AND ins.b = ani.b
AND ins.c = ani.c
        ;

        -- Now that we have the FK pointing to the new table,
        -- we can drop the redundant columns.
ALTER TABLE the_table DROP COLUMN a, DROP COLUMN b, DROP COLUMN c;

SELECT * FROM the_table;
SELECT * FROM abc_table;

        -- show it to the world
SELECT a.*
        , c.a, c.b, c.c
FROM the_table a
JOIN abc_table c ON c.id = a.abc_id
        ;

Resultaten:

CREATE TABLE
INSERT 0 7
CREATE TABLE
ALTER TABLE
CREATE INDEX
UPDATE 7
ALTER TABLE
 id |     name     | abc_id 
----+--------------+--------
  1 | Chimpanzee   |      4
  2 | Urang Utang  |      4
  3 | Homo Sapiens |      4
  4 | Mouse        |      3
  5 | Rat          |      3
  6 | Cat          |      1
  7 | Dog          |      2
(7 rows)

 id | a |    b    |    c    
----+---+---------+---------
  1 | 3 | mammals | felix
  2 | 3 | mammals | canae
  3 | 2 | mammals | rodents
  4 | 1 | mammals | apes
(4 rows)

 id |     name     | abc_id | a |    b    |    c    
----+--------------+--------+---+---------+---------
  1 | Chimpanzee   |      4 | 1 | mammals | apes
  2 | Urang Utang  |      4 | 1 | mammals | apes
  3 | Homo Sapiens |      4 | 1 | mammals | apes
  4 | Mouse        |      3 | 2 | mammals | rodents
  5 | Rat          |      3 | 2 | mammals | rodents
  6 | Cat          |      1 | 3 | mammals | felix
  7 | Dog          |      2 | 3 | mammals | canae
(7 rows)

Bewerken:dit lijkt goed genoeg te werken en ik haat het om de neerwaartse stem te zien die ik daar heb geplaatst, dus nutteloze bewerking (CrazyCasta).



  1. Hoe moet ik DDL-wijzigingen migreren van de ene omgeving naar de andere?

  2. Waarom krijg ik java.lang.AbstractMethodError wanneer ik een blob in de db probeer te laden?

  3. update kolommenwaarden met kolom van een andere tabel op basis van voorwaarde

  4. Gegevens afgekapt voor kolom?