У меня есть следующее:
- точек данных, собранных за день со связанной
date
- меткой времени unix.
Iя пытаюсь добиться следующего:
- Фильтрация точек данных в день. то есть предположим, что у меня есть 4 точки данных в день, я пытаюсь уменьшить их до
n
количество данных в день с использованием GROUP BY
.
Я использую следующий запрос:
SELECT *,FLOOR(UNIX_TIMESTAMP(date)/((1440/n)*60))
AS timekey
FROM `tbl`
where date < 'date'
GROUP BY timekey)m
UNION
(SELECT * ,0 As timekey FROM `tbl`
where date > 'date' );
Это, по моему мнению, должно генерировать timekey дляточки данных для любой строки с датой
n
определяет количество точек, которые будут сгруппированы.
Тогда GROUP BY
должно в конечном итоге уменьшить количество точек данных по отношениюдо n
.
Приведенный выше запрос работает для таблицы с более чем 20000 rows
.
для n=2
точек данных перед указанным date
сокращается до 2точек (до 2 строк из 4).
Вот сценарий создания:
CREATE TABLE `tbl_a` (
`id` int(25) NOT NULL AUTO_INCREMENT,
`pid` bigint(11) NOT NULL,
---
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
---
PRIMARY KEY (`id`),
UNIQUE KEY `phase_id_2` (`phase_id`,`date`),
KEY `id` (`id`,`pid`),
KEY `date` (`date`)
) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Query отлично работает для приведенной выше таблицы.
Однако, когда я пытаюсь выполнить тот же запрос с другой базой данных со сравнительно меньшим количеством строк, он не работает должным образом.
Он уменьшает только дату, указанную в запросе.а остальные остаются нетронутыми.
.ie, только строка, соответствующая данному_дате в запросе, уменьшается запросом, а остальные строки остаются нетронутыми.
Сценарий создания тестовой таблицы:
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `date` (`date`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Может ли это быть ошибкой индекса или исключением ядра СУБД?
Действия по воссозданию проблемы:
Создать тестовую таблицу:
CREATE TABLE `test` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`),
KEY `date` (`date`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Вставить данные:
INSERT INTO test (date) VALUES ('2015-11-01 00:00:00');
INSERT INTO test (date) VALUES ('2015-11-01 06:00:00');
INSERT INTO test (date) VALUES ('2015-11-01 12:00:00');
INSERT INTO test (date) VALUES ('2015-11-01 18:00:00');
INSERT INTO test (date) VALUES ('2016-11-01 00:00:00');
INSERT INTO test (date) VALUES ('2016-11-01 06:00:00');
INSERT INTO test (date) VALUES ('2016-11-01 12:00:00');
INSERT INTO test (date) VALUES ('2016-11-01 18:00:00');
INSERT INTO test (date) VALUES ('2016-11-02 00:00:00');
INSERT INTO test (date) VALUES ('2016-11-02 06:00:00');
INSERT INTO test (date) VALUES ('2016-11-02 12:00:00');
INSERT INTO test (date) VALUES ('2016-11-02 18:00:00');
INSERT INTO test (date) VALUES ('2017-11-02 00:00:00');
INSERT INTO test (date) VALUES ('2017-11-02 06:00:00');
INSERT INTO test (date) VALUES ('2017-11-02 12:00:00');
INSERT INTO test (date) VALUES ('2017-11-02 18:00:00');
Выполнить запрос:
SELECT * FROM
(SELECT *,FLOOR(UNIX_TIMESTAMP(date)/((1440/2)*60))
AS timekey
FROM `test`
where date < '2017-11-02'
GROUP BY timekey) m
UNION
(SELECT * ,0 As timekey FROM `test`
where date > '2017-11-02');
Вышеуказанное должно:
- уменьшить все точки данных до
2017-11-02
, что должно дать результат 10.