MySQL запрос, если заявление

0

Чтобы это было просто, позвольте сказать, что я делаю базовый счетчик страниц в php, который хранит подсчеты для каждой страницы в таблице mysql. В таблице было 2 столбца: PAGE_ID и COUNT.

Я добавил следующий код на каждую страницу:

$query = "INSERT INTO table VALUES ('$page_id', '1')
         ON duplicate KEY UPDATE COUNT=COUNT+1";

$result = mysqli_query($cxn, $query);

Чтобы каждый пользователь просматривал страницу, запускает счетчик только после того, как я добавил сеансы PHP. В основном, если вы просматриваете страницу, page_id хранится в сеансе, а счетчик php-кода проверяет этот сеанс перед запуском счетчика. Работал отлично в моем собственном тестировании.

На некоторых страницах появилось слишком много просмотров, я подозревал дубликаты, поэтому я начал регистрировать IP-адреса и агенты пользователя. Оказывается примерно в 10% случаев, IP запускает счетчик для одной и той же страницы 2-3 раза за несколько минут.

Первый вопрос Что может быть причиной дубликатов? Проблема, похоже, происходит в основном с IE8 и Safari, но у меня также есть хотя бы один экземпляр этого события с IE7 и IE6. Любая известная проблема с php-сессиями? Должен ли я использовать файлы cookie вместо этого?

Часть 2: Я изменил таблицу таким образом, чтобы теперь она сохраняла последнюю метку времени unix и последний IP-адрес, который вызывал счетчик.

Я хочу изменить свой запрос, чтобы перед запуском "COUNT = COUNT + 1" он проверял следующее:

If the current IP is the same as the last stored IP for this page {

     check that it been at least 5 minutes before doing COUNT=COUNT+1

} else { COUNT=COUNT+1; }

Второй вопрос Как написать это в запросе mysql, сохраняя мой оператор "ON duplicate KEY"?

Я понимаю, что это утверждение не будет на 100% точным, но пока я не смогу понять, почему сессия не работает, это сработает. Мой сайт имеет низкий трафик, и я редко получаю более 1 посетителей на одной странице в течение 5 минут.

Спасибо

Теги:
counter

4 ответа

2

Я бы посоветовал вам попытаться выяснить, можете ли вы исправить PHP, но игнорируя это. Вы можете сохранить unixtimestamp, деленный на 300 (IE, с 5-минутными интервалами)

$query = "INSERT INTO OtherTable VALUES ('$ page_id', '$ IP_ADDRESS', (UNIX_TIMESTAMP (NOW())/300))";

Если обновленные записи равны 0, вам не нужно обновлять количество страниц.

  • 0
    Разделение временной метки на 5-минутные интервалы является хорошей идеей. Это не совсем полное доказательство, поскольку оно зависит от того, когда в течение этих 5-минутного периода первый подсчитывает его. На мой взгляд, это также потребует от меня использования одной строки на просмотр страницы. Как я могу заставить его работать, используя одну строку на идентификатор страницы и один запрос MySQL?
  • 0
    Если бы вы сделали ключ уникальным для page_id, ip_address был бы значительно меньше. Единственное реальное решение, если вы этого не сделали, - это исправить обработку вашего сеанса, что является другой историей.
1

1. Что может вызвать дубликаты?

На некоторых страницах появилось слишком много просмотров, я подозревал дубликаты, поэтому я начал регистрировать IP-адреса и агенты пользователя. Оказывается примерно в 10% случаев, IP запускает счетчик для одной и той же страницы 2-3 раза за несколько минут.

Невозможно узнать, будет ли хост, запрашивающий страницу, за NAT-маршрутизатором, - вам запрос будет иметь тот же IP-адрес, но на самом деле это другой хост. Куки или сеанс помогут вам изолировать на каждой рабочей станции, хотя мне интересно, когда вы будете писать информацию в базу данных.

2. Как написать это в запросе mysql, сохраняя инструкцию "ON duplicate KEY"?

Я не вижу необходимости в COUNT = COUNT + 1, потому что SQL имеет функцию COUNT:

  SELECT page_id,
         COUNT(*) 'num_hits'
    FROM ZZZ_NETWORK
   WHERE page_id = ?
GROUP BY page_id

Если вы использовали следующую структуру для ZZZ_NETWORK:

  • page_id, первичный ключ
  • ip_address, первичный ключ
  • временная метка, первичный ключ

... вам не нужно было бы заниматься дублированием ключевых манипуляций, и это позволит вам узнать, сколько хитов вы получили в определенный день, неделю, месяц/и т.д. Включение метки времени гарантирует, что никогда не будет дубликатов.

Через месяц у меня будет тысячи строк в моей таблице, если я использую одну строку на странице.

Пространство на диске - это дешево, и у вас есть временная метка, так что вы можете сделать datamine бесценным для отчетности. Но вам также не нужно хранить все данные - вы можете архивировать его, сбросив данные в файл, чтобы вы могли получить его, если это необходимо.

Я не понимаю, как это будет гарантировать, что я никогда не получу дубликат.

Временная метка включает в себя как дату (декабрь 25/09), так и время (07:00:00 AM). Некоторые типы данных datetime доходят до долей секунды. Это делает невозможным иметь одинаковые дату и время для заданного page_id с заданным IP-адресом - я не могу быстро нажать кнопку обновления, даже если бы захотел. Таким образом, записи никогда не могут быть дублирующими, потому что последний из трех столбцов будет иметь разное значение каждый раз (каламбур не предназначен).

  • 0
    Спасибо за ваш ответ. Вы должны иметь в виду, что это веб-сайт с низким трафиком. 30 просмотров за страницу в день топы. Один и тот же IP-адрес, один и тот же пользовательский агент 3 раза в течение 4 минут заставляет меня поверить, что это один и тот же человек на одной машине, который запускает счетчик более одного раза. Это происходит примерно в 12% случаев. Моя идея состояла в том, чтобы иметь 1 строку на page_id вместо 1 строки на просмотр страницы. Через месяц в моей таблице будут тысячи строк, если я буду использовать одну строку на просмотр страницы. Как вы думаете?
  • 0
    Мои дубликаты не происходят в одно и то же время. Они происходят в течение периода от нескольких секунд до нескольких минут. Если бы я настроил таблицу так, как вы предлагаете, мне все равно пришлось бы проверять, что одна и та же комбинация page_id и ip не регистрируется в промежуток времени, который я считаю слишком близким. Я также не хочу делать так, чтобы он считал количество просмотров только один раз для каждого IP. Если вы вернетесь завтра или через несколько часов, я хочу, чтобы это считалось просмотром другой страницы. Я просто не хочу получать несколько подсчетов за те же 5 минут "сеанса".
Показать ещё 1 комментарий
0

Я думаю, что могу найти способ исправить мою проблему с сеансом. Фактически, я переключился с сеансов на файлы cookie.

Многие мои страницы получают представление через iframe. В iframe возникла проблема с браузерами IE. IE не смог прочитать данные cookie из iframe, если я не добавлю заголовок p3p.

Я добавил заголовок p3p, и теперь он работает правильно. Я так устал от Microsoft и их идеи безопасности. Я также не знаю, что такое p3p, но здесь, как это выглядит в php.

header ( "p3p:CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\"");
0

Что вы ищете, это инструкция CASE: http://dev.mysql.com/doc/refman/5.0/en/case-statement.html

Пример CASE:

SELECT name,
       (CASE WHEN is_happy THEN "Happy!"
        ELSE "sad." END) as happiness 
FROM user_state;

Они также могут использоваться в UPDATE и INSERT.

Я подозреваю, что вы хотите посмотреть на вещи IE. У меня были аналогичные проблемы в прошлом, и мне пришлось использовать javascript для отскока кликов. Я не уверен, если бы пользователи IE дважды щелкали по вещам или если это был IE, то это было странно.

  • 0
    Спасибо за ваш ответ. Я наткнулся на документацию с инструкциями CASE, но я не совсем понимаю, как ее применять. Есть ли у вас какие-либо учебные пособия или легко объясненные примеры того, как использовать случаи в php SQL-запросах? Что касается кликабельных элементов IE, в этом случае код счетчика является частью страницы. Пользователям не нужно ничего щелкать, чтобы вызвать это, просто загрузите страницу. В моих тестах, когда вы загружаете страницу в первый раз, она считается равной 1, но если вы обновляете ее, она этого не делает, так как сеанс искал этот page_id в первый раз. Я сомневаюсь, что люди закрывают и открывают свой браузер 3 раза подряд!
  • 0
    Помог ли пример, который я добавил выше?

Ещё вопросы

Сообщество Overcoder
Наверх
Меню