Рисуем графики

Матеріал з NoDeny
Перейти до навігації Перейти до пошуку

Нарисовать график несложно. Это делается в 2 шага:

  1. Подготавливаем данные и сохраняем в базе данных
  2. Выводим график :)

Поставим задачу: вывести график количества платежей на каждый день.

Количество платежей:

SELECT UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(time))) tm, COUNT(*) n
FROM pays GROUP BY tm ORDER BY tm

Пояснение:

  1. Платежи хранятся в таблице pays
  2. COUNT(*) n - считает количество записей и записывает в "переменную" n (запись в n исключительно для удобства)
  3. UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(time))) tm - довольно сложная конструкция. Проанализируем по частям:
    • Поле time хранит и дату и время платежа. А нам нужна только дата. Т.е. нужно отбросить время
    • Время можно отбросить командой DATE()
    • Проблема в том, что NoDeny для уменьшения размера данных везде хранит время в виде называемом unixtimestamp. По сути это число (которое указывает на количество секунд прошедших сс 01.01.1970). Команда DATE() принимает не unixtimestamp, а дату
    • FROM_UNIXTIME(time) преобразует unixtimestamp в дату
    • UNIX_TIMESTAMP() делает обратное преобразование даты в unixtimestamp
    • Таким образом, SELECT UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(time))) - преобразование в дату, отбрасывание времени, преобразование в unixtimestamp
  4. GROUP BY tm - группирует результат по дням (дни мыф записали в "переменную" tm)

Кроме sql нам нужно дать имя графику. Это просто уникальная последовательность символов. Назовем график pays_stat.

Теперь напишем код. Создадим файл /usr/local/nodeny/web/demo.pl и дадим ему права на чтение вебсервером. Содержимое файла:

use strict;
use JSON;

sub go
{
 my($url) = @_;

 my $graph_name = 'pays_stat';

 if( !ses::input('make') )
 {
    my $param = to_json({
        a       => 'ajGraph',
        domid   => 'main_block',
        group   => $graph_name,
        y_title => 'кол-во',
        type    => 1
    });
    Doc->template('base')->{document_ready} .= "nody.ajax($param);";
    return;
 }

 my $points = [];
 my $db = Db->sql(
    "SELECT UNIX_TIMESTAMP(DATE(FROM_UNIXTIME(time))) tm, COUNT(*) n ".
    "FROM pays GROUP BY tm ORDER BY tm"
 );
 while( my %p = $db->line ) { push @$points, [ 1000*$p{tm}, $p{n} ]; }

 Save_webses_data(
    module=>'ajGraph', data=>{ points=>$points, group=>$graph_name, descr=>'Количество пплатежей' }
 );

 $url->redirect();
}

1;