Сгруппировать результаты запроса по-разному в зависимости от сервера - PullRequest
0 голосов
/ 29 сентября 2019

У меня есть две таблицы, которые я хочу объединить по одному атрибуту (Sensor_id). Затем я хочу использовать GROUP BY для того же атрибута, но мне нужен результат - атрибут DESD ORDER BY Timestamp. Поэтому я использовал подзапрос сначала ORDER BY Timestamp DESC, а затем внешний запрос будет GROUP BY Sensor_id
Первая таблица: Sensors_colocation

=========================================================================================
| Sensor_id | Sensor_longitude | Sensor_latitude | Paese | Pseudonimo | limit1 | limit2 |
=========================================================================================

Вторая таблица: log

===========================================
| Id | Mac_reali | Mac_random | Timestamp |
===========================================

Использование

SELECT * FROM log AS L JOIN Sensors_colocation AS S ON L.Id = S.Sensor_id ORDER BY L.Id ASC, L.Timestamp DESC

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

SELECT * FROM (
    SELECT * FROM log AS L JOIN Sensors_colocation AS S ON L.Id = S.Sensor_id 
    ORDER BY L.Id ASC, L.Timestamp DESC) AS temp
GROUP BY temp.Id

на одном сервере, я получаю результаты, отсортированные по метке времени DESC и сгруппированные по идентификатору. На другом сервере (который имеет ту же структуру, но другие данные), я получаю результаты, отсортированные по метке времени ASC и сгруппированные по идентификатору. Я не понимаю, почему, если я использую подзапрос, ORDER BY, который у меня есть во внутреннем запросе, не рассматривается. Можешь мне помочь?

РЕДАКТИРОВАТЬ: Моя цель состоит в том, чтобы иметь все атрибуты соединенных таблиц, но только последнюю запись о метке времени каждого идентификатора.

EDIT2:

Не работает:

10.1.41-MariaDB-0+deb9u1

CREATE TABLE `log` (
  `Id` int(11) NOT NULL,
  `Mac_reali` int(11) NOT NULL,
  `Mac_random` int(11) NOT NULL,
  `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
ALTER TABLE `log`
  ADD PRIMARY KEY (`Id`,`Timestamp`);

CREATE TABLE `Sensors_colocation` (
  `Sensor_id` int(11) NOT NULL,
  `Sensor_longitude` decimal(7,6) NOT NULL,
  `Sensor_latitude` decimal(8,6) NOT NULL,
  `Paese` varchar(32) NOT NULL,
  `Pseudonimo` varchar(32) NOT NULL,
  `limit1` int(11) NOT NULL,
  `limit2` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
ALTER TABLE `Sensors_colocation`
  ADD PRIMARY KEY (`Sensor_id`);

Работает:

5.6.33-log


CREATE TABLE IF NOT EXISTS `log` (
  `Id` int(11) NOT NULL,
  `Mac_reali` int(11) NOT NULL,
  `Mac_random` int(11) NOT NULL,
  `Timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`Id`,`Timestamp`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS `Sensors_colocation` (
  `Sensor_id` int(11) NOT NULL,
  `Sensor_longitude` decimal(7,6) NOT NULL,
  `Sensor_latitude` decimal(8,6) NOT NULL,
  `Paese` varchar(32) NOT NULL,
  `Pseudonimo` varchar(32) NOT NULL,
  `limit1` int(11) NOT NULL,
  `limit2` int(11) NOT NULL,
  PRIMARY KEY (`Sensor_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

EDIT3: рассмотреть вывод внутреннего запроса (я не пишу некоторые атрибуты, которые нам не нужны)


Id | Mac_reali | Timestamp | Sensor_id | Pseudonimo

1 | 30 | "2019-09-29 17:27:33" | 1 | Manarola(Stazione)
1 | 23 | "2019-09-29 17:25:33" | 1 | Manarola(Stazione)
1 | 57 | "2019-09-29 17:23:33" | 1 | Manarola(Stazione)
2 | 12 | "2019-09-29 17:28:42" | 2 | Vernazza(Stazione)
2 | 33 | "2019-09-29 17:26:42" | 2 | Vernazza(Stazione)
2 | 12 | "2019-09-29 17:24:42" | 2 | Vernazza(Stazione)
3 | 23 | "2019-09-29 17:33:42" | 3 | Monterosso(Stazione)
3 | 17 | "2019-09-29 17:31:42" | 3 | Monterosso(Stazione)
3 | 16 | "2019-09-29 17:29:42" | 3 | Monterosso(Stazione)

С "рабочего" сервера, из внешнего запроса я получаю

Id | Mac_reali | Timestamp | Sensor_id | Pseudonimo

1 | 30 | "2019-09-29 17:27:33" | 1 | Manarola(Stazione)
2 | 12 | "2019-09-29 17:28:42" | 2 | Vernazza(Stazione)
3 | 23 | "2019-09-29 17:33:42" | 3 | Monterosso(Stazione)

С "не работающего" сервера я получаю противоположное упоминание Timestamp (как будто ORDER BY игнорируется)

Id | Mac_reali | Timestamp | Sensor_id | Pseudonimo

1 | 57 | "2019-09-29 17:23:33" | 1 | Manarola(Stazione)
2 | 12 | "2019-09-29 17:24:42" | 2 | Vernazza(Stazione)
3 | 16 | "2019-09-29 17:29:42" | 3 | Monterosso(Stazione)

1 Ответ

1 голос
/ 29 сентября 2019

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

Рассмотрим этот подход, использующий коррелированный подзапрос, чтобы гарантировать, чтонет другой log записи для того же id с большим timestamp:

SELECT * 
FROM log l
INNER JOIN sensors_colocation s ON l.id = s.sensor_id 
WHERE NOT EXISTS (
    SELECT 1
    FROM log l1
    WHERE l1.id = l.id AND l1.timestamp > l.timestamp
)
ORDER BY l.id ASC, l.timestamp DESC

Если вы используете MySQL 8.0, вы можете получить тот же результат, используя оконную функцию ROW_NUMBER()для ранжирования записей по убыванию отметки времени в группах записей, имеющих одинаковый id, и последующей фильтрации по верхней записи для каждой группы:

SELECT *
FROM (
    SELECT 
        l.*, 
        s.*,
        ROW_NUMBER() OVER(PARTITION BY l.id ORDER BY l.timestamp DESC) rn
    FROM log l
    INNER JOIN sensors_colocation s ON l.id = s.sensor_id 
) x
WHERE rn = 1

Примечание: для производительности необходим индекс на log(id, timestamp).

...