這是我的對方回答,擴展到三列:
-- 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
;
結果:
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)
編輯:這似乎是工作不夠好,我討厭看到向下投我放在那裏,如此無用的編輯(CrazyCasta)。
如果UPDATE採用_FOREVER_,那麼是否可能是因爲缺少new_table(a,b,c)'上的唯一索引? –
你'分析了old_table;分析new_table;'首先? –
@EgorRogov我沒有,但現在這樣做,它只是說「分析」。然後我讀了一篇說「它收集靜態信息」的文檔,但我不確定我完全理解它應該做什麼。我是否應該從中收集一些信息,或者它只是讓查詢更快的一種神奇方式? – CrazyCasta