Добавление столбца скользящего среднего в таблицу с использованием значений из предыдущих 2 записей - PullRequest
0 голосов
/ 20 октября 2019

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

Я хотел бы добавить в эту таблицу столбец, в котором для каждой строки будет отображаться СРЕДНЕЕ предыдущих ДВУХ баллов. присуждается ТО пользователю.

Users
+----+----------------------+
| id | name                 |
+----+----------------------+
|  1 | Flossie Schamberger  |
|  2 | Lawson Graham        |
|  3 | Hadley Reilly        |
+----+----------------------+

Bid Forms
+----+-----------------+
| id | name            |
+----+-----------------+
|  1 | Summer 2017     |
|  2 | Winter 2017     |
|  3 | Summer 2018     |
|  4 | Winter 2019     |
|  5 | Summer 2019     |
+----+-----------------+

Points
+-----+---------+--------------------+------------+------------+
| id  | user_id | leave_bid_forms_id | bid_points | date       |
+-----+---------+--------------------+------------+------------+
|   1 |       1 |                  1 |          6 | 2016-06-19 |
|   2 |       2 |                  1 |          8 | 2016-06-19 |
|   3 |       3 |                  1 |         10 | 2016-06-19 |
|   4 |       1 |                  2 |          4 | 2016-12-18 |
|   5 |       2 |                  2 |          8 | 2016-12-18 |
|   6 |       3 |                  2 |          4 | 2016-12-18 |
|   7 |       1 |                  3 |         10 | 2017-06-18 |
|   8 |       2 |                  3 |         12 | 2017-06-18 |
|   9 |       3 |                  3 |          4 | 2017-06-18 |
|  10 |       1 |                  4 |          4 | 2017-12-17 |
|  11 |       2 |                  4 |          4 | 2017-12-17 |
|  12 |       3 |                  4 |          2 | 2017-12-17 |
|  13 |       1 |                  5 |         16 | 2018-06-17 |
|  14 |       2 |                  5 |         12 | 2018-06-17 |
|  15 |       3 |                  5 |         10 | 2018-06-17 |
+-----+---------+--------------------+------------+------------+

Для каждой строки в таблице баллов я бы хотел, чтобы столбец Average_points рассчитывался следующим образом.

Столбец среднего балла - это среднее значение для этих пользователей ПРЕДЫДУЩАЯ2 баллаТаким образом, для первой записи в таблице для каждого пользователя среднее значение, очевидно, равно 0, поскольку им не было присуждено ни одного предыдущего балла.

Предыдущие 2 балла для каждого пользователя должны быть определены с использованием столбца даты.

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

+-----+---------+--------------------+------------+-----------------+
| id  | user_id | leave_bid_forms_id | date       | averaged_points |
+-----+---------+--------------------+------------+-----------------+
|   1 |       1 |                  1 | 2016-06-19 |               0 |    ( 0 + 0 ) / 2 
|   2 |       2 |                  1 | 2016-06-19 |               0 |    ( 0 + 0 ) / 2 
|   3 |       3 |                  1 | 2016-06-19 |               0 |    ( 0 + 0 ) / 2 
|   4 |       1 |                  2 | 2016-12-18 |               3 |    ( 6 + 0 ) / 2 
|   5 |       2 |                  2 | 2016-12-18 |               4 |    ( 8 + 0 ) / 2 
|   6 |       3 |                  2 | 2016-12-18 |               5 |    ( 10 + 0) / 2 
|   7 |       1 |                  3 | 2017-06-18 |               5 |    ( 4 + 6 ) / 2 
|   8 |       2 |                  3 | 2017-06-18 |               8 |    ( 8 + 8 ) / 2 
|   9 |       3 |                  3 | 2017-06-18 |               7 |    ( 4 + 10) / 2 
|  10 |       1 |                  4 | 2017-12-17 |               7 |    ( 10 + 4) / 2 
|  11 |       2 |                  4 | 2017-12-17 |              10 |    ( 12 + 8) / 2 
|  12 |       3 |                  4 | 2017-12-17 |               4 |    ( 4 + 4 ) / 2 
|  13 |       1 |                  5 | 2018-06-17 |               7 |    ( 4 + 10) / 2 
|  14 |       2 |                  5 | 2018-06-17 |               8 |    ( 4 + 12) / 2  
|  15 |       3 |                  5 | 2018-06-17 |               3 |    ( 2 + 4 ) / 2 
+-----+---------+--------------------+------------+-----------------+

Я пытался использовать подзапросы для решения этой проблемы, поскольку AVG, похоже, не подвержен влиянию любого предложения LIMIT, которое у меня есть.

До сих пор я придумал

select id, user_id, leave_bid_forms_id, `date`, 
(
    SELECT
          AVG(bid_points) 
          FROM (
            Select `bid_points`
            FROM points as p2
            ORDER BY p2.date DESC
            Limit 2
                ) as thing
      ) AS average_points
from points as p1

Это в этом sqlfiddle , но, если честно, я здесь не в себе.

Я на правильном пути? Хотите знать, если кто-то сможет показать мне, где мне нужно настроить вещи, пожалуйста!

Спасибо.

РЕДАКТИРОВАТЬ

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

Я добавил это к этому sqlfiddle, чтобы показать, что он работает

. исправлено sql для соответствия приведенному выше коду:

select p.*,
       IFNULL(( (coalesce(points_1, 0) + coalesce(points_2, 0)) /
         ( (points_1 is not null) + (points_2 is not null) )
       ),0) as prev_2_avg
from (select p.*,
             (select p2.bid_points
              from points p2
              where p2.user_id = p.user_id and
                    p2.date < p.date
              order by p2.date desc
              limit 1
             ) as points_1,

             (select p2.bid_points
              from points p2
              where p2.user_id = p.user_id and
                    p2.date < p.date
              order by p2.date desc
              limit 1, 1
             ) as points_2

      from points as p
     ) p;

Хотя я собираюсь задать еще один вопрос о том, как лучше сделать эту динамику с помощью числа предыдущих poingt, которое необходимо усреднить.

1 Ответ

1 голос
/ 20 октября 2019

Вы можете использовать оконные функции , которые были представлены в MySQL 8.

select p.*,
       avg(points) over (partition by user_id
                         order by date
                         rows between 2 preceding and 1 preceding
                        ) as prev_2_avg
from p;

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

select p.*,
       ( (coalesce(points_1, 0) + coalesce(points_2, 0)) /
         ( (points_1 is not null) + (points_2 is not null) )
       ) as prev_2_avg
from (select p.*,
             (select p2.points
              from points p2
              where p2.user_id = p.user_id and
                    p2.date < p.date
              order by p2.date desc
              limit 1
             ) as points_1,
             (select p2.points
              from points p2
              where p2.user_id = p.user_id and
                    p2.date < p.date
              order by p2.date desc
              limit 1, 1
             ) as points_2
      from p
     ) p;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...