Следующее имеет слишком много подвыборов на мой вкус, но оно генерирует желаемый результат в MySQL, если каждый тик и каждый рефид происходят отдельно, по крайней мере, один раз в таблице.
Начните с запроса, который генерирует каждую пару тиков и рефидов. Следующее использует таблицу для генерации пар, поэтому, если какой-либо тик никогда не появится в базовой таблице, он также будет отсутствовать в генерируемых парах. То же самое относится и к рефидам, хотя ограничение «Все рефиды будут иметь значения при тике = 1» должно гарантировать, что последний никогда не произойдет.
SELECT tick, refid FROM
(SELECT refid FROM chadwick WHERE tick=1) AS r
JOIN
(SELECT DISTINCT tick FROM chadwick) AS t
Используя это, сгенерируйте каждый отсутствующий тик, пару refid, а также самый большой тик, который существует в таблице, путем выравнивания по refid и присоединению & theta; & ge; к тику. Сгруппируйте по сгенерированному тику, выполните рефид, так как требуется только одна строка для каждой пары. Ключом к фильтрации существующих тиковых пар refid является предложение HAVING
. Строго говоря, вы можете опустить HAVING
; результирующий запрос вернет существующие строки с их существующими значениями.
SELECT tr.tick, tr.refid, MAX(c.tick) AS ctick
FROM
(SELECT tick, refid FROM
(SELECT refid FROM chadwick WHERE tick=1) AS r
JOIN
(SELECT DISTINCT tick FROM chadwick) AS t
) AS tr
JOIN chadwick AS c ON tr.tick >= c.tick AND tr.refid=c.refid
GROUP BY tr.tick, tr.refid
HAVING tr.tick > MAX(c.tick)
Один последний выбор из вышеперечисленного как дополнительный выбор, присоединенный к исходной таблице для получения значения для данного клика, возвращает новые строки для таблицы.
INSERT INTO chadwick
SELECT missing.tick, missing.refid, c.value
FROM (SELECT tr.tick, tr.refid, MAX(c.tick) AS ctick
FROM
(SELECT tick, refid FROM
(SELECT refid FROM chadwick WHERE tick=1) AS r
JOIN
(SELECT DISTINCT tick FROM chadwick) AS t
) AS tr
JOIN chadwick AS c ON tr.tick >= c.tick AND tr.refid=c.refid
GROUP BY tr.tick, tr.refid
) AS missing
JOIN chadwick AS c ON missing.ctick = c.tick AND missing.refid=c.refid
;
Производительность на примере таблицы вместе с индексами (tick, refid)
и (refid, tick)
:
+----+-------------+------------+-------+-------------------+----------+---------+----------+------+---------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+-------+-------------------+----------+---------+----------+------+---------------------------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 3 | |
| 1 | PRIMARY | c | ALL | tick_ref,ref_tick | NULL | NULL | NULL | 6 | Using where; Using join buffer |
| 2 | DERIVED | <derived3> | ALL | NULL | NULL | NULL | NULL | 9 | Using temporary; Using filesort |
| 2 | DERIVED | c | ref | tick_ref,ref_tick | ref_tick | 5 | tr.refid | 1 | Using where; Using index |
| 3 | DERIVED | <derived4> | ALL | NULL | NULL | NULL | NULL | 3 | |
| 3 | DERIVED | <derived5> | ALL | NULL | NULL | NULL | NULL | 3 | Using join buffer |
| 5 | DERIVED | chadwick | index | NULL | tick_ref | 10 | NULL | 6 | Using index |
| 4 | DERIVED | chadwick | ref | tick_ref | tick_ref | 5 | | 2 | Using where; Using index |
+----+-------------+------------+-------+-------------------+----------+---------+----------+------+---------------------------------+
Как я уже сказал, слишком много подвыборов. Временная таблица может помочь в решении вопросов.
Чтобы проверить отсутствующие галочки:
SELECT clo.tick+1 AS missing_tick
FROM chadwick AS chi
RIGHT JOIN chadwick AS clo ON chi.tick = clo.tick+1
WHERE chi.tick IS NULL;
Это вернет хотя бы одну строку с отметкой, равной 1 + наибольшая отметка в таблице. Таким образом, наибольшее значение в этом результате можно игнорировать.