Заполнение пробелов в дате самым последним значением - PullRequest
0 голосов
/ 13 января 2012

Я разрабатываю сценарий в моей компании, который будет извлекать из нашего SCM информацию об активности исходного кода, такую ​​как количество измененных строк, для данного продукта с течением времени. Все изменения для данного продукта, которые происходят в течение одного дня, объединяются в одну запись в таблице MySQL, что-то вроде этого:

+------------+-------+------+
| date       | prod  | line |
+------------+-------+------+
| 2011-11-25 | prod2 |  471 |
| 2011-11-28 | prod2 |  389 |
+------------+-------+------+

Затем я реплицирую таблицу с кумулятивными результатами, используя внутреннее объединение и суммирование:

+------------+-------+------+
| date       | prod  | line |
+------------+-------+------+
| 2011-11-25 | prod2 |  471 |
| 2011-11-28 | prod2 |  860 |
+------------+-------+------+

Теперь я хочу создать таблицу, в которой будет по одной записи на каждый день для каждого продукта. Я смог сделать это, присоединившись к таблице календаря. Однако при создании новых записей в поле line должно быть указано последнее накопленное значение для этого продукта, а не какое-либо жестко заданное значение по умолчанию, например, NULL или 0:

+------------+-------+------+
| date       | prod  | line |
+------------+-------+------+
| 2011-11-25 | prod2 |  471 |
| 2011-11-26 | prod2 |  471 |
| 2011-11-27 | prod2 |  471 |
| 2011-11-28 | prod2 |  860 |
+------------+-------+------+

Я решил эту проблему двумя неудовлетворительными способами:

  1. Сначала заполните пробелы в датах, , затем , рассчитайте совокупную сумму
  2. Зацикливание на каждом элементе финальной таблицы, сохраняя последние ненулевые элементы в переменной @user.

Первое решение стало чрезвычайно неэффективным, когда мой стол стал достаточно большим. Второе решение выполняет свою работу, но я пытался найти более элегантное решение. Вот код, который создает таблицу с NULL:

INSERT INTO final SELECT d.date,f.prod,p.line
FROM calendar AS d
CROSS JOIN
    (SELECT DISTINCT prod FROM cumulative) AS f
LEFT JOIN cumulative AS p USING (date,prod) ;

Есть идеи? Я использую MySQL.

1 Ответ

0 голосов
/ 13 января 2012

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

Таким образом, вместо исходной таблицы, выглядящей так

+------------+-------+------+
| date       | prod  | line |
+------------+-------+------+
| 2011-11-25 | prod2 |  471 |
| 2011-11-28 | prod2 |  389 |
+------------+-------+------+

будет выглядеть так:

+------------+-------+------+
| date       | prod  | line |
+------------+-------+------+
| 2011-11-25 | prod2 |  471 |
| 2011-11-26 | prod2 |    0 |
| 2011-11-27 | prod2 |    0 |
| 2011-11-28 | prod2 |  389 |
+------------+-------+------+

Что касается самой промежуточной суммы, то ваш автор отчетов можетбыть в состоянии сделать это быстрее, чем SQL.Если бы MySQL поддерживал функции управления окнами, вы бы просто написали что-то вроде

select date, prod, 
       sum(line) over (partition by prod order by date)
from prod

, хотя даже тогда создатель отчетов мог бы работать быстрее.

На платформах, которые не поддерживают функции управления окнами,вам просто нужна сумма в подзапросе.

select p1.prod, p1.date, 
       (select sum(line) from prod 
        where prod = p1.prod and date <= p1.date) as num_lines
from prod p1
order by p1.prod, p1.date
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...