3

刚开始玩并测试亚马逊的红移。我需要做的一件事是我可以在 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 不是红移中的函数,因此出现了我的问题。你们知道我可以达到相同结果的方法吗?

弄清楚了:

( 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(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), ' .') ) * 256) + (REVERSE( LEFT(REVERSE(ip_address), STRPOS(REVERSE(ip_address), '.')-1) ) * 1)'.')+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)'.')+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)

4

2 回答 2

2

哇,看到这个问题,我的眼睛都在流泪,尽管我敢肯定,鉴于 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 中使用)。

在旁注中,我很惊讶地看到inet在 PostgreSQL 中没有定义 from 到 bigint 的转换,因为我期望只能'127.0.0.1'::inet::bigint编写CAST(CAST('127.0.0.1' AS inet) AS bigint).

于 2013-06-29T12:14:29.560 回答
1

split_part(ip, '.', n)应该这样做。

于 2013-06-28T21:39:21.790 回答