1

是否有一种简单/有效的方法可以在 Snowflake 中创建代理键?

在此处输入图像描述

想象一下这个数据集将被选择到一个表中,在插入过程中添加了一个 battery_id 列,它是映射到代理键的 battery_uuid 列。在这种情况下,具体情况可能会变成例如 [1,1,2,1,1,2,3]。Snowflake 中的序列没有这个功能,因为它变成了 [1,2,3,4,5,6,7]。最好在插入期间完成此映射,但是,如果需要,也可以在插入后完成。作为上下文:添加此列是因为 UUID 上的连接不是高性能的。

4

2 回答 2

1

这是你可以做到的

CREATE TABLE thetable (event_id string, batt_id string, serial_number string, batt_key number);
INSERT INTO thetable VALUES('1','bat1','1',0);
INSERT INTO thetable VALUES('2','bat1','1',0);

因此,使用您想要的基本形式的表格,其中包含一些虚拟行来显示“我们想要使用基于 battery_id 的现有密钥的预先存在的数据。出于打字原因,我缩小了列名,并使用数字字符串而不是 UUID ,但点仍然成立。

CREATE OR REPLACE SEQUENCE batt_key_seq;

WITH new_data(event_id, batt_id, serial_number) AS (
    SELECT * FROM VALUES 
        ('11','bat1', '10'),
        ('12','bat1', '10'),
        ('13','bat2', '11'),
        ('14','bat1', '10'),
        ('15','bat1', '10'),
        ('16','bat2', '11'),
        ('17','bat3', '12')
), new_data_with_keys AS (
    SELECT d.batt_id
        ,COALESCE(t.batt_key, batt_key_seq.nextval) AS batt_key
    FROM (
        SELECT DISTINCT batt_id 
        FROM new_data
    ) AS d
    LEFT JOIN thetable AS t 
        ON d.batt_id = t.batt_id
    QUALIFY row_number() OVER (PARTITION BY d.batt_id ORDER BY event_id) = 1
)
SELECT n.*, k.batt_key
FROM new_data AS n
JOIN new_data_with_keys AS k 
    ON n.batt_id = k.batt_id
;

所以 ROW_NUMBER() 部分是只捕获一个现有的行(因此在开始时在现有数据中插入双数据),我觉得这可能会以其他方式更清洁,但它可以完成工作。

但实际上,您获得了密钥,找到了现有的密钥,并为新数据提供了新的密钥,然后可以以这种丰富的形式插入数据。

我在测试中注意到的是,我的关键是每次运行跳跃 4 次,然后切换到

,IFF(t.batt_key is not null, t.batt_key, batt_key_seq.nextval) AS batt_key

没有解决这个问题。

因此,将关键查找部分分开,例如

WITH new_data(event_id, batt_id, serial_number) AS (
    SELECT * FROM VALUES 
        ('11','bat1', '10'),
        ('12','bat1', '10'),
        ('13','bat2', '11'),
        ('14','bat1', '10'),
        ('15','bat1', '10'),
        ('16','bat2', '11'),
        ('17','bat3', '12')
), missing_keys AS (
    SELECT d.batt_id
        ,batt_key_seq.nextval AS batt_key
    FROM (
        SELECT DISTINCT batt_id 
        FROM new_data
    ) AS d
    LEFT JOIN thetable AS t 
        ON d.batt_id = t.batt_id
    WHERE t.batt_id IS NULL
), old_keys AS (
    SELECT distinct d.batt_id
        ,t.batt_key
    FROM (
        SELECT DISTINCT batt_id 
        FROM new_data
    ) AS d
    LEFT JOIN thetable AS t 
        ON d.batt_id = t.batt_id
    WHERE t.batt_id IS NOT NULL
), new_data_with_keys AS (
    SELECT * FROM missing_keys
    UNION ALL
    SELECT * FROM old_keys
)
SELECT n.*, k.batt_key
FROM new_data AS n
JOIN new_data_with_keys AS k 
    ON n.batt_id = k.batt_id
;

现在新键不会跳过/浪费。

双连接与键空间浪费的性能差异是您可能需要测试和/或了解您将看到多少新的现有数据以及因此发生多少浪费的东西。如果第二个的性能差异很大,您可以随时重新键入数据,尽管这些键在表之外使用,以后可能需要更新大量数据。

于 2021-03-21T00:13:05.220 回答
1

如果您的目标是出于连接性能的目的将字符串转换为数字,我建议使用HASH函数。在您的情况下,您可以简单地创建一个新列并将值更新HASH(battery_uuid)为创建代理键。然后利用该新列进行连接。如果您的自然键超过 2 列,这仍然适用于您,因为该HASH函数允许使用多个列。

https://docs.snowflake.com/en/sql-reference/functions/hash.html

于 2021-03-20T14:46:16.373 回答