如何在 AMAZON REDSHIFT 中将 userip 转换为整数
Posted
技术标签:
【中文标题】如何在 AMAZON REDSHIFT 中将 userip 转换为整数【英文标题】:How to Convert userip to integer in AMAZON REDSHIFT 【发布时间】:2013-06-28 20:19:54 【问题描述】:刚开始玩并测试亚马逊的红移。我需要做的一件事是我可以在 sql 中轻松完成的操作是将 userip 更改为整数。这是在 mssql 中通过一个标量函数完成的,该函数使用 parsename 来分解 ip 编号并通过常量将它们倍增。
CAST(
(CAST(PARSENAME(@IP,4) AS BIGINT) * 16777216) +
(CAST(PARSENAME(@IP,3) AS BIGINT) * 65536) +
(CAST(PARSENAME(@IP,2) AS BIGINT) * 256) +
CAST(PARSENAME(@IP,1) AS BIGINT)
AS BIGINT)
这就是它的样子供参考。
正如我所料,parsename 不是 redshift 中的函数,因此我的问题出现了。你们知道我可以达到相同结果的方法吗?
想通了:
( LEFT(ip_address, STRPOS(ip_address, '.')-1) * 16777216) + (LEFT(SUBSTRING(ip_address, LEN(LEFT(ip_address, STRPOS(ip_address, '.')+1))), LEN (ip_address) - LEN(LEFT(ip_address, STRPOS(ip_address, '.')-1)) - LEN(LEFT(REVERSE(ip_address), STRPOS(REVERSE(ip_address), '.')-1)) - 2) , STRPOS( SUBSTRING(ip_address, LEN(LEFT(ip_address, STRPOS(ip_address, '.')+1)), LEN(ip_address) - LEN(LEFT(ip_address, STRPOS(ip_address, '.')-1))) - LEN(LEFT(REVERSE(ip_address), STRPOS(REVERSE(ip_address), '.')-1)) - 2), '.')-1) * 65536) + (RIGHT( SUBSTRING(ip_address, LEN(LEFT( ip_address, STRPOS(ip_address, '.')+1)), LEN(ip_address) - LEN(LEFT(ip_address, STRPOS(ip_address, '.')-1)) - LEN(LEFT(REVERSE(ip_address), STRPOS( REVERSE(ip_address), '.')-1)) - 2), LEN(SUBSTRING(ip_address, LEN(LEFT(ip_address, STRPOS(ip_address, '.')+1)), LEN(ip_address) - LEN(LEFT (ip_address, STRPOS(ip_address, '.')-1)) - LEN(LEFT(REVERSE(ip_address), STRPOS(REVERSE(ip_address), '.')-1)) - 2)) - STRPOS(SUBSTRING(ip_address) , LEN(L EFT(ip_address, STRPOS(ip_address, '.')+1)), LEN(ip_address) - LEN(LEFT(ip_address, STRPOS(ip_address, '.')-1)) - LEN(LEFT(REVERSE(ip_address), STRPOS(REVERSE(ip_address), '.')-1)) - 2), '.') ) * 256) + (REVERSE( LEFT(REVERSE(ip_address), STRPOS(REVERSE(ip_address), '.')- 1) ) * 1 )
【问题讨论】:
“在 sql 中”->“在 Microsoft SQL Server 中”? “SQL”是查询语言,它不是产品。感谢您提到您正在使用 Redshift(ParAccel 的一个非常旧的 PostgreSQL 版本的专有分支),而不仅仅是说“PostgreSQL”。此外,最好发布您自己问题的答案,而不是尽可能编辑您的答案。 【参考方案1】:哇,看到这个问题,我的眼睛都在流泪,不过我敢肯定,鉴于 Redshift 施加的限制,你没有太多选择。
我仍然很惊讶你必须做一些相当麻烦的事情。你不能至少创建一个或两个SQL
函数来整理它吗?还是Redshift连CREATE FUNCTION ... LANGUAGE sql
都不支持?
作为参考,在适当的 PostgreSQL 中你会这样做:
select (split_part(ip, '.', 1)::bigint << 24) +
(split_part(ip, '.', 2)::bigint << 16) +
(split_part(ip, '.', 3)::bigint << 8) +
(split_part(ip, '.', 4)::bigint);
或使用简单的 SQL 函数:
CREATE OR REPLACE FUNCTION inet_to_bigint(inet) AS $$
SELECT sum(split_part($1::text,'.',octetnum)::bigint << (32 - octetnum*8))
FROM generate_series(1,4) octetnum;
$$ LANGUAGE sql;
或者,几乎可以肯定最有效的是,滥用inet
数据类型的减法运算符:
SELECT (ip - '0.0.0.0')
(如果 Redshift 保留了 inet
数据类型,并且当 ParAccel 从 PostgreSQL 分叉时该功能早在 PostgreSQL 8.1 中存在,这个功能甚至可以在 Redshift 中使用)。
在旁注中,我很惊讶地发现在 PostgreSQL 中没有从 inet
定义到 bigint 的转换,因为我希望只能写 '127.0.0.1'::inet::bigint
,这将是 CAST(CAST('127.0.0.1' AS inet) AS bigint)
的简写.
【讨论】:
Redshift 不支持函数或 IP 类型 +1 。 . .第一个解决方案似乎适用于 RedShift。【参考方案2】:split_part(ip, '.', n)
应该这样做。
【讨论】:
我已经尝试使用@jakub,但是在使用亚马逊红移时,split_part 将无法在主节点之外工作。 @PatRickAllen 这些事情在原始问题中值得一提。 “我已经试过了……”。 Amazon 不提供在 Redshift 上测试东西的便捷方法(没有等效的 SQLFiddle,没有免费的测试服务器等),所以如果您标记问题 postgresql,人们会回复适用于 PostgreSQL 的答案。以上是关于如何在 AMAZON REDSHIFT 中将 userip 转换为整数的主要内容,如果未能解决你的问题,请参考以下文章
如何减少在 Amazon Redshift 中将 pandas 数据帧写入表的时间
如何在 Amazon Redshift 中将列从字符串更改为日期?