PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Szybkie zapytanie do normalizacji danych SQL

To jest moja druga odpowiedź, rozszerzona do trzech kolumn:

        -- 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
        ;

Wyniki:

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)

Edycja:wydaje się, że to działa wystarczająco dobrze i nie znoszę zobaczyć mojego głosowania przeciw, więc bezużyteczna edycja (CrazyCasta).



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Konwertuj datę juliańską na datę kalendarzową w Postgresql

  2. Zakończenie NGINX TLS dla PostgreSQL

  3. Lewe sprzężenie zewnętrzne działające jak sprzężenie wewnętrzne

  4. Jak połączyć ciągi w polu ciągu w zapytaniu PostgreSQL „grupuj według”?

  5. Jak przenieść produkcyjną bazę danych do pomostu w Heroku za pomocą pgbackups? Otrzymuję błąd