将PostgreSQL运算符转换为MySQL等价运算符?

时间:2016-11-03 23:08:33

标签: mysql postgresql

您好我有以下PostgreSQL声明:

SELECT sub1.date_evt AS event_date, SUM(sub1.UC_IP) as UCIP, SUM(sub1.NON_UC_IP) as OUTIP
        FROM (
            SELECT  TO_CHAR(event_date, 'yyyy-mm-dd') as date_evt,
            case when ip <<= inet('10.0.0.0/8') then 1
            when ip <<= inet('128.218.0.0/16') then 1
            else 0 END AS UC_IP,
            case when  ip <= inet('10.0.0.0/8') then 0
            when ip <<= inet('128.218.0.0/16') then 0
            else 1
            END AS NON_UC_IP
            FROM link_history
            WHERE url_link = (SELECT `id` FROM links WHERE base_url = 'qt4gt8')
        ) AS sub1
        GROUP BY sub1.date_evt
        ORDER BY sub1.date_evt;

我试图将它转换成MySQL中相同的东西,我已经转换了数据并将其导入MySQL,使用INET_NTOA()函数将IP值保存到MySQL数据库中的无符号INT列中。 / p>

我试图将其转换为但无法找到运营商的答案&lt;&lt; = 此运营商我不知道它的作用,也找不到PostgreSQL网站上的文档。

我想也许这是一个按位等于运算符或其他东西,但我似乎无法让它在MySQL中运行,这是我的MySQL语句。

SELECT sub1.date_evt AS event_date, SUM(sub1.UC_IP) as UCIP, SUM(sub1.NON_UC_IP) as OUTIP
        FROM (
            SELECT event_date as date_evt,
            case 
                when ip << INET_ATON('10.0.0.8') then 1
                when ip << INET_ATON('128.218.0.16') then 1
            else 0 END AS UC_IP,
            case 
                when ip << INET_ATON('10.0.0.8') then 0
                when ip << INET_ATON('128.218.0.16') then 0
            else 1
            END AS NON_UC_IP FROM link_history
            WHERE url_link = (SELECT `id` FROM links WHERE base_url = 'qt4gt8')
        ) AS sub1
        GROUP BY sub1.date_evt
        ORDER BY sub1.date_evt;

运行时,我得不到任何结果,这是不正确的,我应该从我的数据集中得到16行。

MySQL似乎也不喜欢IP范围值,例如&#39; 169.230.0.0/16'所以我只是将它放在给定IP的最高范围内,删除0 \并保持给定IP的8/16,我不确定这是否会起作用。但是如果不知道如何解决&lt;&lt; = ,我就无法修复查询的其余部分。

更新:
好的,我得到的最新信息,我有以下查询:

SELECT sub1.date_evt AS event_date, SUM(sub1.UC_IP) as UCIP, SUM(sub1.NON_UC_IP) as OUTIP
        FROM (
            SELECT event_date as date_evt,
            case 
                WHEN INET_ATON(ip) >= INET_ATON('10.0.0.0') AND INET_ATON(ip) <= (INET_ATON('10.0.0.0') + (1 << (32-8) - 1)) THEN 1 #8
                WHEN INET_ATON(ip) >= INET_ATON('128.218.0.0') AND INET_ATON(ip) <= (INET_ATON('128.218.0.0') + (1 << (32-16) - 1)) then 1  #128.218.0.16
                WHEN INET_ATON(ip) >= INET_ATON('64.54.0.0') AND INET_ATON(ip) <= (INET_ATON('64.54.0.0') + (1 << (32-16) - 1)) then 1 #64.54.0.16
                WHEN INET_ATON(ip) >= INET_ATON('169.230.0.0') AND INET_ATON(ip) <= (INET_ATON('169.230.0.0') + (1 << (32-16) - 1)) then 1  #169.230.0.16
            else 0 END AS UC_IP,
            case 
                WHEN INET_ATON(ip) >= INET_ATON('10.0.0.0') AND INET_ATON(ip) <= (INET_ATON('10.0.0.0') + (1 << (32-8) - 1)) THEN 0 #8
                WHEN INET_ATON(ip) >= INET_ATON('128.218.0.0') AND INET_ATON(ip) <= (INET_ATON('128.218.0.0') + (1 << (32-16) - 1)) THEN 0  #128.218.0.16
                WHEN INET_ATON(ip) >= INET_ATON('64.54.0.0') AND INET_ATON(ip) <= (INET_ATON('64.54.0.0') + (1 << (32-16) -1)) THEN 0 #64.54.0.16
                WHEN INET_ATON(ip) >= INET_ATON('169.230.0.0') AND INET_ATON(ip) <= (INET_ATON('169.230.0.0') + (1 << (32-16) - 1)) THEN 0  #169.230.0.16
            else 1
            END AS NON_UC_IP FROM link_history
            WHERE url_link = (SELECT `id` FROM links WHERE base_url = 'qt4gt8')
        ) AS sub1
        GROUP BY sub1.date_evt
        ORDER BY sub1.date_evt

我的数据库表现在看起来像这样:

CREATE TABLE `link_history` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `url_link` int(11) DEFAULT NULL,
  `event_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `ip` varchar(15) DEFAULT NULL,
  `cidr` varchar(15) DEFAULT NULL,
  `ref_url` text,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=930100 DEFAULT CHARSET=latin1;



id  url_link event_date         ip              cidr     ref_url
3204    70  2011-02-05 07:20:00 67.180.61.248   32       http://ucsfmeded.blogspot.com/2010/11/calvin-chou-md-phd-appointed-academy.html

但是我发现MYSQL表的结果与Postgres表的结果不完全匹配。在PostgreSQL中,我获得了16个数据结果,在MySQL中我获得了29行。 SUM列也是关闭的。在我看来,由于时间分配,GROUP BY无法正常工作。我是否必须将DATE-TIME分解为单独的列,或者是否有办法进行GROUP BY,它只计算DATE?我怎样才能确定IP RANGE是否正常工作?

3 个答案:

答案 0 :(得分:5)

已知operator&#39;包含在或等于&#39;

when ip <<= inet('128.218.0.0/16') then 1

所以你在这里做的是试图找出你的ip是否属于128.218.0.0/16网络。那就是IP地址是否在128.218.0.0到128.218.0.255

之内

所以你可以用数字比较来做到这一点。但问题是,为什么你要从功能丰富,功能更强大,速度更快的数据库转移到没有那么多功能的数据库,速度更慢,有时甚至是正确的数据库?

以上大致相当于

when ip >= inet_aton('128.218.0.0') AND ip <= INET_ATON('128.218.0.255) then 1

类似地

when ip >= inet_aton('10.0.0.0') AND ip <= INET_ATON('10.0.255.255) then 1

答案 1 :(得分:1)

ip <<= inet('10.0.0.0/8')

将是

ip >> (32-8) = INET_ATON('10.0.0.0') >> (32-8)

考虑到这种方式你不能使用索引。但它对您的查询无关紧要。

如果要使用索引搜索某个范围内的IP,可以使用BETWEEN条件:

ip BETWEEN INET_ATON('10.0.0.0') AND INET_ATON('10.0.0.0') + (1 << (32-8)) - 1

如果您将ips存储为字符串且子网掩码为/8/16/24,则可以与LIKE进行比较。

/8表示 - 第一个数字相等。 /16表示 - 前两个数字相等。 /24表示 - 前三个数字相等。

因此,如果ip处于10.0.0.0/8范围内,您可以简单地使用

ip LIKE '10.%'

对于'128.218.0.0/16'范围:

ip LIKE '128.218.%'

答案 2 :(得分:0)

好的,谢谢大家(@ e4c5和@Paul Spiegel)的有用答案。这是最终的工作查询。

SELECT sub1.date_evt AS event_date, SUM(sub1.UC_IP) as UCIP, SUM(sub1.NON_UC_IP) as OUTIP
        FROM (
            SELECT DATE_FORMAT(event_date, '%Y-%m-%d') as date_evt,
            case 
                WHEN INET_ATON(ip) >= INET_ATON('10.0.0.0') AND INET_ATON(ip) <= (INET_ATON('10.0.0.0') + (1 << (32-8) - 1)) THEN 1 #8
                WHEN INET_ATON(ip) >= INET_ATON('128.218.0.0') AND INET_ATON(ip) <= (INET_ATON('128.218.0.0') + (1 << (32-16) - 1)) then 1  #128.218.0.16
                WHEN INET_ATON(ip) >= INET_ATON('64.54.0.0') AND INET_ATON(ip) <= (INET_ATON('64.54.0.0') + (1 << (32-16) - 1)) then 1 #64.54.0.16
                WHEN INET_ATON(ip) >= INET_ATON('169.230.0.0') AND INET_ATON(ip) <= (INET_ATON('169.230.0.0') + (1 << (32-16) - 1)) then 1  #169.230.0.16
            else 0 END AS UC_IP,
            case 
                WHEN INET_ATON(ip) >= INET_ATON('10.0.0.0') AND INET_ATON(ip) <= (INET_ATON('10.0.0.0') + (1 << (32-8) - 1)) THEN 0 #8
                WHEN INET_ATON(ip) >= INET_ATON('128.218.0.0') AND INET_ATON(ip) <= (INET_ATON('128.218.0.0') + (1 << (32-16) - 1)) THEN 0  #128.218.0.16
                WHEN INET_ATON(ip) >= INET_ATON('64.54.0.0') AND INET_ATON(ip) <= (INET_ATON('64.54.0.0') + (1 << (32-16) -1)) THEN 0 #64.54.0.16
                WHEN INET_ATON(ip) >= INET_ATON('169.230.0.0') AND INET_ATON(ip) <= (INET_ATON('169.230.0.0') + (1 << (32-16) - 1)) THEN 0  #169.230.0.16
            else 1
            END AS NON_UC_IP FROM link_history
            WHERE url_link = (SELECT `id` FROM links WHERE base_url = 'qt4gt8')
        ) AS sub1
        GROUP BY sub1.date_evt
        ORDER BY sub1.date_evt