2016-11-03 109 views
2

嗨,我有以下的PostgreSQL聲明:將PostgreSQL操作符轉換爲與MySQL等價的操作符?

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中,IP值已使用INET_NTOA被保存()函數轉換爲MySQL數據庫中的一個無符號的INT列。

我試圖轉換這一點,但無法找到答案的操作< < =這個操作我不知道它做什麼,並不能找到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範圍值,如'169.230.0.0/16',所以我剛剛將它放在給定IP的最高範圍內,刪除0 \並保持它爲8 /對於給定的IP,16我不知道這是否會起作用。但不知道如何解決< < =我無法修復查詢的其餘部分。

UPDATE:
好與他們給我我有以下查詢的最新信息:

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分成不同的列,或者是否有辦法在只計算DATE的地方執行GROUP BY?我如何確定IP RANGE正常工作?

+0

是的,下面解決,感謝您的幫助! – DevelumPHP

回答

5

operator被稱爲「包含在或或等於」

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

haha​​ha,有趣的答案,不幸的是,這只是我給的任務,我想我可以使用BETWEEN ... AND ...函數來做類似的事情,謝謝。 – DevelumPHP

+0

是的,你將不得不將每個網絡轉換爲較低和較高的地址 – e4c5

+0

嘗試使用以下之間但它不會返回任何東西,IP已經存儲爲一個無符號的INT,'WHEN ip BETWEEN INET_ATON( '10.0.0.0')和INET_ATON('10.0.0.8'),然後1' – DevelumPHP

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.%' 
0

好感謝大家(@ e4c5和@保羅週刊)爲有用的答案。這是最後的工作查詢。

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