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

Не уверен, что это простой запрос или нет, но по какой-то причине не могу понять ...

У меня есть запись изменений статуса в порядке убывания (от самого старого до самого нового):

  Name       Status               Time
   A          Up        2018-06-21 00:07:00.000000
   A          Up        2018-05-21 00:07:00.000000
   A         Down       2018-04-21 00:07:00.000000
   A         Down       2018-03-21 00:07:00.000000
   A          Up        2018-02-21 00:07:00.000000
   A         Down       2018-01-21 00:07:00.000000

Но я хочу только вернуть уникальные изменения в столбец Status, что дает мне список случаев, когда статус менялся. Поэтому ответ будет таким:

  Name       Status               Time
   A          Up        2018-05-21 00:07:00.000000
   A         Down       2018-03-21 00:07:00.000000
   A          Up        2018-02-21 00:07:00.000000
   A         Down       2018-01-21 00:07:00.000000

Обратите внимание, как результат возвращает записи с марта и мая, а не с апреля и июня, поскольку это были времена, когда статус изменялся из другого состояния.

Мой запрос в настоящее время выполняет какое-то присоединение, поэтому я также не уверен, как / где это вписать в запрос:

SELECT
      Instrument.Name AS Name,
      Status.Name AS Status,
      Operation.Time AS Time,
FROM Operation
      INNER JOIN Instrument ON Instrument.Id = Operation.InstrumentId
      INNER JOIN Status ON Status.Id = Operation.StatusId
WHERE Instrument.Name = ?;

Ответы [ 3 ]

0 голосов
/ 05 января 2019

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

      SELECT
      Instrument.Name AS Name,
      DISTINCT(Status.Name) AS Status,
      Operation.Time AS Time,
FROM Operation
      INNER JOIN Instrument ON Instrument.Id = Operation.InstrumentId
      INNER JOIN Status ON Status.Id = Operation.StatusId
WHERE ( Name,
      Status,
      Time ) 
      IN
   (SELECT
      Instrument.Name AS Name1,
      Status.Name AS Status1,
      Operation.Time AS Time1,
FROM Operation
      INNER JOIN Instrument ON Instrument.Id = Operation.InstrumentId
      INNER JOIN Status ON Status.Id = Operation.StatusId
     group by NAME1, Status1 having Time1=min(Time1)
   )
0 голосов
/ 06 января 2019

В другом подходе используется псевдовременная таблица (нельзя использовать фактическую временную таблицу, поскольку MySql не разрешает выдавать несколько подзапросов для одного), то есть исходную таблицу с добавленным к ней «номером строки» в качестве первичного ключа:

SET @row_number = 0;
create table temp as
  SELECT (@row_number:=@row_number + 1) AS row_num, t.* FROM t order by time;
ALTER TABLE temp ADD PRIMARY KEY (row_num);

Тогда запрос становится просто:

select name, status, time from temp temp1
    where temp1.row_num = 1
    or temp1.status <>
       (select temp2.status from temp temp2 where temp2.row_num = temp1.row_num - 1);

drop table temp; /* no longer need this table */
0 голосов
/ 05 января 2019

В идеале вы хотите lag() и выбрать из этого. Позвольте мне предположить, что вы до v8 MySQL.

Один метод является коррелированным подзапросом:

select t.*
from (select t.*,
             (select t2.status
              from t t2
              where t2.time < t.time
              order by t2.time desc
              limit 1
             ) as prev_status
      from t
     ) t
where prev_status is null or prev_status <> status;

В более новых версиях MySQL вы можете просто сделать:

select t.*
from (select t.*,
             lag(status) over (order by time) as prev_status
      from t
     ) t
where prev_status is null or prev_status <> status;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...