Python SQL语句创建基于无组织表的字典

Python SQL语句创建基于无组织表的字典,python,sql,postgresql,dictionary,Python,Sql,Postgresql,Dictionary,我有一个数据量很大的表,大小约为1TB,基于以下模式: CREATE TABLE my_table( col1 character varying, col2 character varying, col3 character varying ); 上述表格包含以下形式的数据: col1 col2 col3 <abc1> <def1> <ghi1> <abc1> <g1> <g2&

我有一个数据量很大的表,大小约为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>

例如,我知道我可以使用我选择的编程语言Python来实现这一点。我想知道的是,是否有可能使用纯SQL实现类似的功能?

老实说,使用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;
请看下面的例子


我不是100%相信使用联合是最有效的方法,但我知道它符合您的标准,即从所有三列中检索不同的字符串并为它们分配所有数字。在Python中这样做要慢得多。

老实说,在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;
请看下面的例子


我不是100%相信使用联合是最有效的方法,但我知道它符合您的标准,即从所有三列中检索不同的字符串并为它们分配所有数字。在Python中这样做要慢得多。

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

CREATE TABLE DistinctStrings ( Id SERIAL NOT NULL, String CHARACTER VARYING NOT NULL ) 我假设您希望保留该表,因此它显然是数据库的一部分,而不是每次填充时都重新创建

像这样插入到这个表中

INSERT INTO DistinctStrings (String) SELECT col1 FROM my_table UNION SELECT col2 FROM my_table UNION SELECT col3 FROM my_table
使用“联合”而不是“联合”都会给你带来你想要的独特性。串口的使用将为您提供ID。

好的,我是从SQL Server的角度来看这一点的,但概念基本相同。据我所知,SERIAL相当于SQL Server中的IDENTITY,因此它将为您提供一个自动递增的密钥。我的解决方案可能如下:

CREATE TABLE DistinctStrings ( Id SERIAL NOT NULL, String CHARACTER VARYING NOT NULL )
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;
我假设您希望保留该表,因此它显然是数据库的一部分,而不是每次填充时都重新创建

像这样插入到这个表中

INSERT INTO DistinctStrings (String) SELECT col1 FROM my_table UNION SELECT col2 FROM my_table UNION SELECT col3 FROM my_table 使用“联合”而不是“联合”都会给你带来你想要的独特性。序列号的使用会给你你的身份证

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)
结果:

 col1 | col2 | col3 
------+------+------
    2 |    3 |    6
    2 |    4 |    7
    1 |    4 |    5
(3 rows)

所需输出中的第二列是否意味着与字符串来自的列相对应?这样,如果我们要扩展您的示例col1 col2 col3 row1:row2:将输出1 | 2 | 3 | 1 | 2 | 3?@misterManager No.。实际上,我想分配表整数ID中的所有字符串。它们在表中的存储顺序对用户来说无关紧要me@misterManager我编辑了我的问题来解释。谢谢你的回复。没问题。希望我的答案就是你想要的!所需输出中的第二列是否意味着与字符串来自的列相对应?这样,如果我们要扩展您的示例col1 col2 col3 row1:row2:将输出1 | 2 | 3 | 1 | 2 | 3?@misterManager No.。实际上,我想分配表整数ID中的所有字符串。它们在表中的存储顺序对用户来说无关紧要me@misterManager我编辑了我的问题来解释。谢谢你的回复。没问题。希望我的答案就是你想要的!您可以在不使用行号和distinct的情况下完成相同的任务。您的UNION为您处理distinct,您要插入的表上的一个自动递增键将处理ID。。。行号不能重复用于插入到表中,因为它总是从1开始,这将要求您在每次加载表时转储它。在这里,所有的排序和内容都超过1TB的数据,我想它的性能不如剥离一点。同意自动递增键,但是我故意把它忘在这里,这样我们只需要一个SELECT语句,而不需要CREATETABLE语句或类似的语句。您可以在没有行号和distinct的情况下完成同样的事情。您的UNION为您处理distinct,您要插入的表上的一个自动递增键将处理ID。。。行号不能重复用于插入到表中,因为它总是从1开始,这将要求您在每次加载表时转储它。在这里,所有的排序和内容都超过1TB的数据,我想它的性能不如剥离一点。同意使用自动递增键,但我故意不使用它,因此我们只需要一个SELECT语句,而不需要CREATE TABLE语句或类似的语句。