0

标题可能有点混乱。让我解释一下这个问题。我有一个每天加载新记录的管道。此记录包含销售额。关键是<日期、位置、票证、线路>。这些数据被加载到红移表中,然后通过系统读取的视图公开。这个系统有一个限制,票的列是 varchar(10) 但票是 30 个字符的字符串。如果系统只取前10个字符会产生重复。票号可以是“假”号。如果它不等于实数也没关系。所以我正在考虑在 redshift 表上添加一个包含渐进数字的新列。问题是我不能使用标识列,因为属于同一张票的记录必须具有相同的“累进编号”。

这就是我想要的:

地点 线 数量 票号
2020 年 12 月 12 日 67 123...生长激素 1 10 1
2020 年 12 月 12 日 67 123...生长激素 2 5 1
2020 年 12 月 12 日 67 123...生长激素 3 23 1
2020 年 12 月 12 日 23 123...国标 1 13 2
2020 年 12 月 12 日 23 123...国标 2 45 2
... ... ... ... ... ...
2020 年 12 月 12 日 78 123...AG 5 100 153

第二天加载新数据时,我想从 ticket_id 154 开始,依此类推。

每行都有一列,指定插入的时刻。同一天插入的行具有相同的 insert_time。

我的解决方案是:

  1. 插入带有ticket_id 作为dense_rank 的记录。但是每次(我加载新记录,所以每天)ticket_id 都从一个开始,所以......
  2. ...将刚刚插入的行更新为 ticket_id = ticket_id + 我在 ticket_id 列下找到的最大数量 insert_time != max(insert_time)

你认为有更好的解决方案吗?如果存在一个以 <day, location, ticket> 作为输入并返回最多 10 个字符的哈希函数,那就太好了。

4

1 回答 1

0

因此,从评论看来,您不能添加维度表来仅查找标识每个工单的数字或 10 个字符串,因为这将是数据模型更改。这可能是最好和最准确的方法。

您询问了一个哈希函数来执行此操作,并且有几个。但首先让我们谈谈哈希——它们采用不同长度的字符串并从中生成签名。由于此过程可以显着减少字符数,因此 2 个不同的字符串可能会生成相同的哈希。哈希值越长,发生这种碰撞的几率就越低,但几率永远不会为零。由于您只能有 10 个字符,因此设置了哈希冲突的几率。

Redshift 上的 md5() 函数将获取一个字符串并从中生成一个 32 个字符的字符串(以 16 个字符为基数)。md5(day::text || location || ticket:text) 将从您提到的列中生成这样的哈希值。这个过程可以产生 16^32 个可能的不同字符串,这是一个很大的数字。

但你只想要一个 10 个字符的字符串。好消息是,像 md5() 这样的哈希函数将字符串之间的差异传播到整个输出中,因此您可以选择任意 10 个字符来使用。这样做会将唯一值的数量减少到 16^10 或大约 1.1 万亿 - 仍然是一个很大的数字,但如果您有数十亿行,您可能会看到冲突。一种改进方法是对 md5() 输出进行 base64 编码,然后截断为 10 个字符。这样做将需要一个 UDF,但会将可能的哈希数提高到 1.1E18 - 大一百万倍。如果您希望输出为整数,您可以使用 strtol() 将十六进制字符串转换为整数,但 10 位数字只有 100 亿个可能值。

因此,如果您确定要使用哈希,这是很有可能的。只要记住哈希的作用。

于 2020-12-14T17:03:37.297 回答