Добро пожаловать на Pro Pawn - Портал о PAWN-скриптинге.
Показано с 1 по 7 из 7
  1. #1
    Аватар для execution
    Пользователь

    Статус
    Оффлайн
    Регистрация
    09.03.2018
    Сообщений
    255
    Репутация:
    24 ±

    Как получить данные (статистику по онлайну) из таблицы за 7 дней

    Доброе утро. Логирую отыгранное время в секундах каждый день. Хотел сделать вывод онлайна на протяжении всей недели (вывода дня недели, даты и времени), но вот сложилось сомнение а стоит ли оно? Мне необходимо будет получить кол-во секунд в каждый день недели (7 подзапросов), получения unix времени (7 подзапросов (для вывода дня недели на русском на стороне сервера)) и получения даты (7 подзапросов) - в итоге 21 подзапрос и стоит ли оно? Возможно я не в том направлении рассматриваю реализацию?
    Последний раз редактировалось DeimoS; 30.06.2020 в 10:39. Причина: Перенос сообщений в отдельную тему и добавление префикса

  2. #2
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от execution Посмотреть сообщение
    Доброе утро. Логирую отыгранное время в секундах каждый день. Хотел сделать вывод онлайна на протяжении всей недели (вывода дня недели, даты и времени), но вот сложилось сомнение а стоит ли оно? Мне необходимо будет получить кол-во секунд в каждый день недели (7 подзапросов), получения unix времени (7 подзапросов (для вывода дня недели на русском на стороне сервера)) и получения даты (7 подзапросов) - в итоге 21 подзапрос и стоит ли оно? Возможно я не в том направлении рассматриваю реализацию?
    Создаёшь таблицу с календарём на 7 дней назад (хотя можно даже создавать на год назад и на год вперёд каждый старт сервера. Занимать это действие будет пару секунд времени). Далее пишешь один запрос, в котором получаешь дату 7 последних дней и к ней, через "LEFT JOIN", добавляешь количество отыгранных часов.

    Вот, собственно, дарю готовую функцию для создания календаря:
    1. stock CreateCalendarTable({MySQL, _}:__connection_id, days_count, const start_date[] = "CURDATE()", const direction[] = "-")
    2. {
    3. #define TABLE_CALENDAR_NAME_ "sys_calendar"
    4.  
    5. new tick = GetTickCount();
    6.  
    7. mysql_query(__connection_id,
    8. "DROP TABLE IF EXISTS `"#TABLE_CALENDAR_NAME_"`", false);
    9.  
    10. mysql_query(__connection_id,
    11. "CREATE TABLE `"#TABLE_CALENDAR_NAME_"`(`id` int(11) NOT NULL,`date` date NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=utf8;", false);
    12.  
    13. mysql_query(__connection_id,
    14. "ALTER TABLE `"#TABLE_CALENDAR_NAME_"` ADD PRIMARY KEY (`id`);", false);
    15.  
    16. mysql_query(__connection_id,
    17. "ALTER TABLE `"#TABLE_CALENDAR_NAME_"` MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;", false);
    18.  
    19. new query_string[100+11+1];
    20. for(new i; i < days_count; i++)
    21. {
    22. format(query_string, sizeof(query_string), "INSERT INTO "#TABLE_CALENDAR_NAME_"(date)VALUES((%s) %s INTERVAL %d DAY)",
    23. start_date, direction, i);
    24. mysql_query(__connection_id, query_string, false);
    25. }
    26.  
    27.  
    28. "\
    29. [MySQL] Календарь успешно создан. \
    30. Название таблицы: \""#TABLE_CALENDAR_NAME_"\" \
    31.   [Количество дат: %d]. \
    32.   Времени затрачено: %d мс\
    33.   ", days_count, GetTickCount()-tick);
    34.  
    35. #undef TABLE_CALENDAR_NAME_
    36. }


    В OnGameModeInit просто вставляешь
    1. CreateCalendarTable(mysql, 366*2, "CURDATE()+INTERVAL 1 YEAR");

    И функция создаст календарь, примерно, на год назад и на год вперёд, удалив старую таблицу, если она была.

    Ну а запрос на получение данных пробуй сам составить. В интернете есть хорошие статьи на тему "JOIN" в MySQL.
    Последний раз редактировалось DeimoS; 30.06.2020 в 10:40.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  3. Пользователь сказал cпасибо:
    execution (30.06.2020)
  4. #3
    Аватар для execution
    Пользователь

    Статус
    Оффлайн
    Регистрация
    09.03.2018
    Сообщений
    255
    Репутация:
    24 ±
    Немного не доходит, зачем использовать таблицу с календарными днями? Если можно сделать так
    1. SELECT SUM( seconds ) AS day_online, WEEKDAY( DATE ) AS week_day, DATE
    2. FROM `accounts_online`
    3. WHERE account_id =118161
    4. AND DATE > DATE_ADD( CURDATE( ) , INTERVAL -7
    5. DAY )


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

  5. #4
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от execution Посмотреть сообщение
    Немного не доходит, зачем использовать таблицу с календарными днями? Если можно сделать так
    1. SELECT SUM( seconds ) AS day_online, WEEKDAY( DATE ) AS week_day, DATE
    2. FROM `accounts_online`
    3. WHERE account_id =118161
    4. AND DATE > DATE_ADD( CURDATE( ) , INTERVAL -7
    5. DAY )


    Но вот пришло в голову то, чтобы считать онлайн с понедельника и мне кажется, эта таблица как раз кстати
    Потому что MySQL не может вернуть данные, которых нет. Следовательно, если ты не собираешься для каждого аккаунта, который не заходил на сервер, ежедневно создавать в таблице со статистикой онлайна записи, указывая 0 в качестве времени онлайна, то MySQL попросту не сможет тебе сообщить, что за такую-то дату игрок никакого времени не наиграл. А значит тебе либо придётся пропускать дни (что будет смотреться криво, как по мне), либо уже в самом моде реализовывать подбор даты для пропущенных дней (но тогда нужно учитывать и високосные года, и то, что у разных месяцев разные количества дней, и ещё некоторые моменты), либо нужно создавать временную таблицу с календарём на 7 дней каждый запрос (что неразумно), либо создавать такой календарь и отталкиваться от него, что является самым оптимальным вариантом.

    - - - Добавлено - - -

    Собственно, вот такой запрос будет генерировать ответ в виде статистики за последние 7 дней.
    1. SELECT
    2. WEEKDAY(s.date) AS week_day,
    3. s.date,
    4. IFNULL(SUM(a.seconds), 0) AS total
    5. FROM
    6. sys_calendar as s
    7. LEFT JOIN
    8. accounts_online as a
    9. ON
    10. (s.`date` = a.`DATE` AND a.account_id=118161)
    11. WHERE
    12. s.date >= CURDATE()-INTERVAL 7 DAY
    13. AND
    14. s.date <= CURDATE()
    15. GROUP BY s.`date`
    16. ORDER BY s.`date` DESC

    И в случае, если игрок не играл в какой-то день, этот день так же будет находится в запросе. Можно даже
    1. IFNULL(SUM(a.seconds), 0) AS total

    заменить, например, на
    1. IFNULL(SUM(a.seconds), 'Не играл') AS total

    Чтоб не приходилось делать дополнительные условия, а сразу можно было получать готовый текст (правда, придётся пользоваться cache_get_field_type перед извлечением данных)

    Ну и ещё я бы советовал не забывать про DATE_FORMAT, который позволяет форматировать дату ещё на этапе запроса.
    Например, вот так:
    1. DATE_FORMAT(s.`date`, '%d.%m.%Yг') as 'date',

    можно на выходе сразу получить дату в формате: "30.06.2020г".
    Последний раз редактировалось DeimoS; 30.06.2020 в 17:12.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  6. Пользователь сказал cпасибо:
    execution (30.06.2020)
  7. #5
    Аватар для execution
    Пользователь

    Статус
    Оффлайн
    Регистрация
    09.03.2018
    Сообщений
    255
    Репутация:
    24 ±
    Использовал такую конструкцию
    1. SELECT \
    2. WEEKDAY(s.date) AS week_day, \
    3. s.date, \
    4. IFNULL(SUM(a.seconds), 0) AS seconds_count, \
    5. IFNULL(SUM(a.afk_seconds), 0) AS afk_seconds_count \
    6. FROM \
    7. sys_calendar as s \
    8. LEFT JOIN \
    9. accounts_online as a \
    10. ON \
    11. (s.`date` = a.`DATE` AND a.account_id=%d) \
    12. WHERE \
    13. YEARWEEK(CURDATE(), 1) = YEARWEEK(s.date, 1) \
    14. GROUP BY s.`date` \
    15. ORDER BY s.`date` ASC


    И всё было норм, но с недавних пор, возвращает пустую строку. И как только не извивался - всё равно. Изменений не было, подобного результата другим способом нельзя сделать. На что это может повлиять, может кто подсказать?

    UPD: закончился календарь
    Последний раз редактировалось execution; 04.08.2021 в 11:22.

  8. #6
    Аватар для DeimoS
    Модератор?

    Статус
    Оффлайн
    Регистрация
    27.01.2014
    Адрес
    Восточный Мордор
    Сообщений
    5,588
    Репутация:
    1984 ±
    Цитата Сообщение от execution Посмотреть сообщение
    UPD: закончился календарь
    Чтоб такого не было, можешь просто каждый рестарт пересоздавать таблицу с календарём.
    Связаться со мной в VK можно через личные сообщения этой группы
    Заказы не принимаю

    Широко известно, что идеи стоят 0.8333 цента каждая (исходя из рыночной цены 10 центов за дюжину).
    Великих идей полно, на них нет спроса.
    Воплощение идеи в законченную игру требует долгой работы,
    таланта, терпения и креативности, не говоря уж о затратах денег, времени и ресурсов.
    Предложить идею просто, воплотить – вот в чём проблема

    Steve Pavlina

  9. #7
    Аватар для execution
    Пользователь

    Статус
    Оффлайн
    Регистрация
    09.03.2018
    Сообщений
    255
    Репутация:
    24 ±
    Цитата Сообщение от DeimoS Посмотреть сообщение
    Чтоб такого не было, можешь просто каждый рестарт пересоздавать таблицу с календарём.
    Да, так и сделал

 

 

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •