Sql 将行关联到单独表中的不同版本

Sql 将行关联到单独表中的不同版本,sql,postgresql,distinct,Sql,Postgresql,Distinct,我有一个Postgres9.1.4表格,有几百万行。非常小的版本可能是这样的: 掌握 index location ---------------- 1 A 2 C 3 B 4 C 5 C 6 A 我需要对location字段中的每个不同值进行昂贵的计算。我不想使用主表中的此字段,因为我将重复处理同一位置。我想要一个具有不同位置值的表,计算结果将存储在计算字段中: 清晰的 index location calculation -

我有一个Postgres9.1.4表格,有几百万行。非常小的版本可能是这样的:

掌握

index  location
----------------
1      A
2      C
3      B
4      C
5      C
6      A
我需要对location字段中的每个不同值进行昂贵的计算。我不想使用主表中的此字段,因为我将重复处理同一位置。我想要一个具有不同位置值的表,计算结果将存储在计算字段中:

清晰的

index  location  calculation
------------------------------
1      A'        X
2      C'        Y
3      B'        Z
在填充distinct之后,主控和distinct之间的关系不容易确定。我必须做一些数据处理,使位置在计算中起作用。我真的需要第三个表,大约是在我填充distinct的同时创建的,以帮助我将distinct中的每个条目关联回master中的父条目

第三个表可能如下所示:

相关性

master_index  distinct_index
------------------------------
1             1
2             3
3             2
4             3
5             3
6             1
问题是,我不知道如何使用任何简单的SQL实现这一点。我可以使用类似这样的内容作为查询的开始,以填充不同的:

问题是我需要另一个distinct中的数组列来保存这些值,然后我需要使用其他一些程序来解析数组并构造相关表


我是否缺少一种更简单的方法来执行此操作?

您可以仅使用主表和不同的表来执行此操作。您的独特列表(即使来自多个字段)实际上是外键的基础。不同表的唯一值与主表之间存在一对多关系。如果将主表的位置数据上的索引和独特表的位置数据上的唯一索引重新连接在一起,将有助于提高性能。

您可以按如下方式创建“独特”表(不过,我提醒您避免使用SQL关键字作为表名作为列):


这些方法很有效,但你可能需要更有效的方法。创建表之后,为了提高效率,需要添加索引。您还可以使用其他技巧,例如使用自动递增的主键预创建不同的表,并将其用作不同的索引。然后您可以使用insert将数据加载到查询中。

我已经在SQL server上完成了此操作。我想这就是你要找的

您可以使用查询创建不同的表

select MIN("index") "index",location from tmaster
group by location 
并通过下面的查询得到相关表

select M."index" master_index,A."index" distinct_index
 from tmaster M left outer join 
(select MIN("index") "index",location from tmaster
group by location)A
on A.location=M.location

您不需要将相关性放入表中,一个视图或CTE就足够了:(顺便说一句:index是一个保留字;我用zindex替换了它(没有以Z开头的SQL关键字,zDISTINCT也是如此)


顺便说一下:zdistinct CTE与原始问题中的“distinct”表大致相同。只需添加“calculation”字段,您就到家了。(您可以先将其放入单独的视图中)您描述的不是n:m关系,而是1:n关系。因此,您根本不需要
相关性表来实现关系

在一个有“几百万行”的表中冗余地指定位置是次优设计。您应该对其进行规范化。大表将缩小很多(使一切都更快)。将列
master.location
替换为外键列,该外键列引用专用
location
表的新主键。这是应该的方式

master

master\u id loc\u id。。。
-----------------
1          1       ...
2          2
3          3
4          3
5          3
6          1
位置

loc\u id loc\u派生计算
-----------------------------
1 A'X
2 C C'Y
3b'Z
昂贵的计算似乎可以保证在
calc
中冗余存储功能相关的值。但是在您的问题中,关于
loc_派生的
列的计算没有任何内容。如果不是很昂贵(并且经常使用),不应将其包含在
位置
表中,而应为其创建视图或

通常,您会在
master
location
之间添加外键约束,以保证关系的完整性。将来,您会在
master
中添加引用位置的行之前添加位置

怎么去那里?
  • 使用代理整数主键(
    locu id
    )创建
    location

    创建表位置(
    loc_id序列号
    ,loc文本
    ,loc_派生文本--这里真的需要冗余存储吗?
    ,calc text--这里似乎需要冗余存储。
    );
    
    有人建议使用<代码> LOC 本身作为自然主键。我不在其中,认为这是个坏主意。

    • 文本列上的字符串操作和索引要比处理整数慢得多
    • 如果遇到(中间)重复的位置名称,则很难更改位置名称
    • 对位置名称的每次更改都会触发从属表中的其他更新—代理项键不会发生这种情况
    • 大的
      master
      表将更小,只使用一个整数而不是整个字符串来引用
      位置
  • 填写新的
    位置
    表格(我将使用CTE进行计算)

    以x作为(
    选择不同的位置
    从主人那里
    )
    插入位置(loc、loc_导出、计算)
    选择loc、部分计算(loc)、部分计算(loc)
    从x;
    
  • 将loc_id添加到主表

    altertablemaster添加列loc\u id整数;
    
  • 填写列
    loc\u id

    更新主程序m
    设置loc_id=l.loc_id
    从位置l
    其中l.loc=m.loc;
    
  • 滴水器
    create table correlation as
        select m.index as MasterIndex, td.TDIndex
        from master m join
             TDistinct td
             on m.location = td.location
    
    select MIN("index") "index",location from tmaster
    group by location 
    
    select M."index" master_index,A."index" distinct_index
     from tmaster M left outer join 
    (select MIN("index") "index",location from tmaster
    group by location)A
    on A.location=M.location
    
    DROP SCHEMA tmp CASCADE;
    CREATE SCHEMA tmp;
    SET search_path=tmp;
    
    -- Make some data ...
    CREATE TABLE master
            ( zindex INTEGER NOT NULL PRIMARY KEY
            , location CHAR(1) NOT NULL
            );
    INSERT INTO master(zindex,location) VALUES
     (1, 'A')
    ,(2, 'C')
    ,(3, 'B')
    ,(4, 'C')
    ,(5, 'C')
    ,(6, 'A')
            ;
    
        -- a view with a CTE inside
    CREATE VIEW correlation AS (
            WITH zdistinct AS (
                    SELECT MIN(m.zindex) AS zindex
                    , m.location AS location
                    FROM master m
                    GROUP BY m.location
                    )
            SELECT m.zindex AS master_index
                    , d.zindex AS distinct_index
            FROM master m
            JOIN zdistinct d ON m.location = d.location
            );
    
    SELECT * FROM correlation;