2016-11-03 2 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() в столбце INT без знака в базе данных MySQL.

Я попытался преобразовать это, но не могу найти ответ на оператора < < = этого оператора я не знаю, что она делает, и не может найти документацию на веб-сайте 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/16 для данного IP, я не уверен, будет ли это работать одинаково. Но не зная, как решить проблему для < < = Я не могу исправить остальную часть запроса.

UPDATE:
Ok с последней информацией, у меня была у меня есть следующий запрос:

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

Да, решено ниже, спасибо за помощь! – 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

hahaha, смешной ответ, к сожалению, это была просто задача, которую мне дали, я думаю, что могу использовать функции МЕЖДУ ... И ..., чтобы сделать что-то подобное, спасибо. – 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 

Если вы храните ваш IP-адрес в виде строки и ваша маска подсети /8, /16 или /24 затем вы можете просто сравнить с LIKE.

/8 средства - первый номер равен. /16 означает - первые два числа равны. /24 означает - первые три числа равны.

Так Чек, если ф находится в 10.0.0.0/8 диапазоне, вы можете просто использовать

ip LIKE '10.%' 

Для '128.218.0.0/16' диапазона:

ip LIKE '128.218.%' 
0

Ok спасибо всем (@ 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 
Смежные вопросы