0

我有一个基于以下模式的数据密集型表(大小约为 1TB):

CREATE TABLE my_table(
  col1  character varying, 
  col2 character varying, 
  col3 character varying
);

上述表格包含以下形式的数据:

col1     col2    col3
<abc1>   <def1>  <ghi1>
<abc1>   <g1>    <g2>
<g3>     <g1>    <g4>

现在,我想做的是创建一个字典(另一个表),它将表的所有唯一字符串my_table(存在于col1col2col3)映射到一个整数值。例如:

<abc1>    1
<def1>    2
<ghi1>    3
<g1>      4
<g2>      5
<g3>      6
<g4>      7

我知道我可以使用我选择的编程语言(例如 Python)来做到这一点。我想知道的是是否可以使用纯 SQL 来实现这样的目标?

4

3 回答 3

2

老实说,在 SQL 中执行此操作会更轻松。

例如,这可以解决问题:

SELECT DISTINCT ROW_NUMBER() OVER (ORDER BY col ASC) AS row, col FROM 

(SELECT col1 AS col FROM mytable
UNION
SELECT col2 AS col FROM mytable
UNION
SELECT col3 AS col FROM mytable
) AS newtable

ORDER BY row;

请参阅此的SQLFiddle

我不是 100% 确信使用UNIONs 是执行此操作的最有效方法,但我知道它符合您从所有三列中检索不同字符串并将它们分配给所有数字的标准。在 Python 中执行此操作会慢得多。

于 2013-10-16T01:42:29.390 回答
1

好的,我是从 SQL Server 的角度来看的,但概念基本上是相同的。据我了解,这SERIAL相当于IDENTITY在 SQL Server 中,它会为您提供一个自动递增的键。我的解决方案可能如下:

创建表 DistinctStrings
(
   ID SERIAL NOT NULL,
   字符串 CHARACTER VARYING NOT NULL
)

我假设您想保留该表,因此它显然是数据库的一部分,并且不会在您每次填充它时重新创建。

像这样插入这个表

INSERT INTO DistinctStrings(字符串)
SELECT col1 FROM my_table UNION
SELECT col2 FROM my_table UNION
从 my_table 中选择 col3

使用UNION(而不是UNION ALL)将为您提供您正在寻找的独特性。的使用SERIAL将为您提供您的 ID。

于 2013-10-16T01:48:27.443 回答
1
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;

CREATE TABLE bigstrings
        ( col1 varchar
        , col2 varchar
        , col3 varchar
        );

INSERT INTO bigstrings(col1, col2, col3) VALUES
 ('abc1','def1','ghi1')
,('abc1','g1','g2')
,('g3','g1','g4')
        ;

CREATE TABLE allstrings
        ( num BIGSERIAL NOT NULL PRIMARY KEY
        , string varchar NOT NULL UNIQUE
        );

CREATE TABLE nostrings
        ( col1 BIGINT REFERENCES allstrings(num)
        , col2 BIGINT REFERENCES allstrings(num)
        , col3 BIGINT REFERENCES allstrings(num)
        );

INSERT INTO allstrings( string)
SELECT DISTINCT col1 FROM bigstrings bs
 -- not needed on empty allstrings table.
 -- WHERE NOT EXISTS ( SELECT * FROM allstrings nx WHERE nx.string = bs.col1)
        ;

INSERT INTO allstrings( string)
SELECT DISTINCT col2 FROM bigstrings bs
WHERE NOT EXISTS ( SELECT * FROM allstrings nx WHERE nx.string = bs.col2)
        ;

INSERT INTO allstrings( string)
SELECT DISTINCT col3 FROM bigstrings bs
WHERE NOT EXISTS ( SELECT * FROM allstrings nx WHERE nx.string = bs.col3)
        ;

INSERT INTO nostrings(col1,col2,col3)
SELECT s1.num, s2.num, s3.num
FROM bigstrings bs
JOIN allstrings s1 ON s1.string = bs.col1
JOIN allstrings s2 ON s2.string = bs.col2
JOIN allstrings s3 ON s3.string = bs.col3
        ;

SELECT * FROM nostrings;

结果:

 col1 | col2 | col3 
------+------+------
    2 |    3 |    6
    2 |    4 |    7
    1 |    4 |    5
(3 rows)
于 2013-10-16T11:44:19.767 回答