выбрать актуальные значения из БД Firebird - PullRequest
0 голосов
/ 19 ноября 2018

У меня есть таблица в БД Firebird - см. picture


Мне нужно знать актуальную информацию о местоположении (LOCATION) каждого устройства. Каждое устройство имеет уникальный серийный номер (SERIAL_NUMBER). Самым последним местоположением является строка с самыми высокими значениями всех счетчиков (COUNTER1 ... COUNTER6). Я попытался следующий запрос, но он должен быть дополнен, чтобы получить то, что мне нужно. К сожалению, я не знаю, как его изменить.

SELECT LOCATION 
FROM TABLE 
WHERE SERIAL_NUMBER IN (SELECT DISTINCT SERIAL_NUMBER 
                        FROM TABLE) 
ORDER BY COUNTER1, COUNTER2, COUNTER3, COUNTER4, COUNTER5, COUNTER6

Из псевдо-ответа, теперь удаленного:

Мне нужно найти строку для каждого SERIAL_NUMBER с наибольшим значением COUNTER1 и, если он равен COUNTER2, и если он равен COUNTER3 ... COUNTER6. Итак, наконец, это будет набор строк для каждого SERIAL_NUMBER с самой последней информацией о местоположении. Жар-птица вер. 2.5 Дизайн такой как есть и не может быть изменен. Здесь нет столбец метки времени в таблице, чтобы найти последнюю информацию о местонахождении в прямой путь, поэтому наибольшее значение счетчиков представляет собой наиболее текущее местоположение.

1 Ответ

0 голосов
/ 20 ноября 2018

Вот оно: http://sqlfiddle.com/#!17/ff969/1

Вам нужно будет сделать очевидные переходы на разновидность Firebird SQL:

  • Firebird не может вставить много строк одним оператором.
  • Firebird использует синтаксис select FIRST(1) ..... вместо select .... LIMIT 1

Обратите внимание, как я использую один запрос SELECT за другим, начиная с простых запросов, создавая сложные, проверяя каждый простой (что он действительно возвращает то, что мне нужно), прежде чем создавать более сложные конструкции поверх них.

Подробнее о процессе * КАК для увеличения запросов читайте здесь: https://stackoverflow.com/a/51398120/976391


Настройка схемы PostgreSQL 9.6 :

create table tab(
  id /* INTeger NOT NULL AUTO_INCREMENT */ serial primary key,
  ser varchar(20) not null,
  Loc varchar(20) not null,
  c1 integer not null,
  c2 integer not null,
  c3 integer not null,
  c4 integer not null,
  c5 integer not null,
  c6 integer not null
 );

 insert into tab(ser,loc,c1,c2,c3,c4,c5,c6) values
 ('LSE4300308', 'Address 1', 0,0,0, 0,0,0),
 ('LHD4x22414', 'Address 2', 601,504,8, 130,0,0),
 ('LHD4x22414', 'Address 3', 2385,1163,54, 150,0,0),
 ('LSE4300308', 'Address 4', 2209,0,323, 0,0,0),
 ('LSE4300308', 'Address 5', 2257,0,330, 1661,926,0),
 ('LSE4300308', 'Address 6', 2278,0,330, 0,0,0),
 ('LSE4300308', 'Address 7', 2257,0,330, 1661,926,0),
 ('LSE4300308', 'Address 8', 2262,0,330, 1661,926,0),
 ('L873702373', 'Address 9', 12165,25467,1578, 2619,0,0),
 ('L873702373', 'Address A', 12165,25467,1578, 2619,0,0);

 create index t_ser on tab(ser);
 create /* descending */ index t_counters on tab(c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc);

Запрос 1 :

Select * from tab

Результаты

| id |        ser |       loc |    c1 |    c2 |   c3 |   c4 |  c5 | c6 |
|----|------------|-----------|-------|-------|------|------|-----|----|
|  1 | LSE4300308 | Address 1 |     0 |     0 |    0 |    0 |   0 |  0 |
|  2 | LHD4x22414 | Address 2 |   601 |   504 |    8 |  130 |   0 |  0 |
|  3 | LHD4x22414 | Address 3 |  2385 |  1163 |   54 |  150 |   0 |  0 |
|  4 | LSE4300308 | Address 4 |  2209 |     0 |  323 |    0 |   0 |  0 |
|  5 | LSE4300308 | Address 5 |  2257 |     0 |  330 | 1661 | 926 |  0 |
|  6 | LSE4300308 | Address 6 |  2278 |     0 |  330 |    0 |   0 |  0 |
|  7 | LSE4300308 | Address 7 |  2257 |     0 |  330 | 1661 | 926 |  0 |
|  8 | LSE4300308 | Address 8 |  2262 |     0 |  330 | 1661 | 926 |  0 |
|  9 | L873702373 | Address 9 | 12165 | 25467 | 1578 | 2619 |   0 |  0 |
| 10 | L873702373 | Address A | 12165 | 25467 | 1578 | 2619 |   0 |  0 |

Запрос 2 :

Select distinct ser from tab

Результаты

|        ser |
|------------|
| LSE4300308 |
| L873702373 |
| LHD4x22414 |

Запрос 3 :

Select /* First(10) */ * from tab
  where ser = 'LSE4300308'
  order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc
  limit 10 

Результаты :

| id |        ser |       loc |   c1 | c2 |  c3 |   c4 |  c5 | c6 |
|----|------------|-----------|------|----|-----|------|-----|----|
|  6 | LSE4300308 | Address 6 | 2278 |  0 | 330 |    0 |   0 |  0 |
|  8 | LSE4300308 | Address 8 | 2262 |  0 | 330 | 1661 | 926 |  0 |
|  5 | LSE4300308 | Address 5 | 2257 |  0 | 330 | 1661 | 926 |  0 |
|  7 | LSE4300308 | Address 7 | 2257 |  0 | 330 | 1661 | 926 |  0 |
|  4 | LSE4300308 | Address 4 | 2209 |  0 | 323 |    0 |   0 |  0 |
|  1 | LSE4300308 | Address 1 |    0 |  0 |   0 |    0 |   0 |  0 |

Запрос 4 :

Select /* First(1) */ * from tab
  where ser = 'LSE4300308'
  order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc
  limit 1 

Результаты

| id |        ser |       loc |   c1 | c2 |  c3 | c4 | c5 | c6 |
|----|------------|-----------|------|----|-----|----|----|----|
|  6 | LSE4300308 | Address 6 | 2278 |  0 | 330 |  0 |  0 |  0 |

Запрос 5 :

Select t1.ser, 
  ( Select /* First(1) */ loc from tab 
    Where ser = t1.ser
    order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc
    Limit 1)
From (Select distinct ser from tab) as t1

Результаты

|        ser |       loc |
|------------|-----------|
| LSE4300308 | Address 6 |
| L873702373 | Address 9 |
| LHD4x22414 | Address 3 |

Конвертация Firebird 2.1. Обратите внимание - если этот запрос не выполняется очень редко, вы все равно можете лучше изменить структуру базы данных. Независимо от того, что там уже есть, вы все равно можете ДОБАВИТЬ новые вспомогательные таблицы и можете добавить новые triggers, чтобы автоматически обновлять эти новые таблицы. Например, одна дополнительная таблица «последний идентификатор для каждого серийного номера» облегчит вашу жизнь, выполняя команду update or insert каждый раз, когда в местоположения вставляется новая строка.

create table so53371903(
  id integer primary key,
  ser varchar(20) not null,
  Loc varchar(20) not null,
  c1 integer not null,
  c2 integer not null,
  c3 integer not null,
  c4 integer not null,
  c5 integer not null,
  c6 integer not null
 );

 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (0,'LSE4300308', 'Address 1', 0,0,0, 0,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (1,'LHD4x22414', 'Address 2', 601,504,8, 130,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (2,'LHD4x22414', 'Address 3', 2385,1163,54, 150,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (3,'LSE4300308', 'Address 4', 2209,0,323, 0,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (4,'LSE4300308', 'Address 5', 2257,0,330, 1661,926,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (5,'LSE4300308', 'Address 6', 2278,0,330, 0,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (6,'LSE4300308', 'Address 7', 2257,0,330, 1661,926,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (7,'LSE4300308', 'Address 8', 2262,0,330, 1661,926,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (8,'L873702373', 'Address 9', 12165,25467,1578, 2619,0,0)
 ;
 insert into so53371903(id,ser,loc,c1,c2,c3,c4,c5,c6) values
   (9,'L873702373', 'Address A', 12165,25467,1578, 2619,0,0)
 ;

 create index t_ser on so53371903(ser);
 create descending index t_counters on so53371903(c1,c2,c3,c4,c5,c6);

Select * from so53371903;

Select distinct ser from so53371903;

Select first(10) * from so53371903
  where ser = 'LSE4300308'
  order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc;

Select first(1) * from so53371903
  where ser = 'LSE4300308'
  order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc;

Select t1.ser, 
  ( Select First(1) loc from so53371903
    Where ser = t1.ser
    order by c1 desc,c2 desc,c3 desc,c4 desc,c5 desc,c6 desc
   )
From (Select distinct ser from so53371903) as t1;

Примечание: Address 9 и Address 10 имеют одинаковые значения в счетчиках, как и Address 5 и Address 7. Поскольку между ними нет «максимальных счетчиков» - «выигрышная» строка будет выбрана случайным образом. Возможно, сегодня будет один победитель, и выполнение одного и того же запроса через месяц или год даст в этих строках другой результат.

...