您好我有以下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是否正常工作?
答案 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