Генерация нескольких строк на основе одной строки, содержащей нулевое значение после правого соединения - PullRequest
0 голосов
/ 02 апреля 2019

У меня есть программное обеспечение, которое получает данные с нескольких устройств с SNMP. Затем программное обеспечение создает запись в таблице с начальным временем опроса и конечным временем опроса.

Для каждой таблицы SNMP, которую мы получаем, мы помещаем данные в разные таблицы.

В приведенной ниже модели есть одна таблица snmp (FrequencyValue). Таблицы выглядят так:

| Polls |                  |                  |
|-------|------------------|------------------|
| id    | start_time       | end_time         |
|-------|------------------|------------------|
| 1     | 2019-04-01T10:00 | 2019-04-01T10:10 |
| 2     | 2019-04-01T11:00 | 2019-04-01T11:10 |
| 3     | 2019-04-01T12:00 | 2019-04-01T12:10 |

| Devices    |
|------------|
| ip         |
|------------|
| 172.16.1.1 |

| FrequencyValue |         |                  |           |       |
|----------------|---------|------------------|-----------|-------|
|      device_ip | poll_id | timestamp        | frequency | value |
|----------------|---------|------------------|-----------|-------|
|     172.16.1.1 |       1 | 2019-04-01T10:02 |      1000 |    10 |
|     172.16.1.1 |       1 | 2019-04-01T10:02 |      2000 |    20 |
|                |         |                  |           |       |
|     172.16.1.1 |       3 | 2019-04-01T12:02 |      1000 |    10 |
|     172.16.1.1 |       3 | 2019-04-01T12:02 |      2000 |    20 |

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

Вопрос: Чтобы построить график столбца value на frequency, мы хотели бы создать n строк для каждого frequency, в котором был бы столбец value to null.

Пока наш запрос выглядит так:

select p.ip, coalesce(t.timestamp, p.start_time) as "time", t.frequency, t.value
from FrequencyValue as t
right join (
  select p.start_time, p.id, d.ip
  from Polls as p, Devices as d
) as p on (t.poll_id = p.id and t.device_ip = p.ip)

С выводом:

|         ip | timestamp        | frequency | value |
|------------|------------------|-----------|-------|
| 172.16.1.1 | 2019-04-01T10:02 |      1000 |    10 |
| 172.16.1.1 | 2019-04-01T10:02 |      2000 |    20 |
|            |                  |           |       |
| 172.16.1.1 | 2019-04-01T11:00 |      null |  null |
|            |                  |           |       |
| 172.16.1.1 | 2019-04-01T12:02 |      1000 |    10 |
| 172.16.1.1 | 2019-04-01T12:02 |      2000 |    20 |

Что мы на самом деле хотим, так это:

|         ip | timestamp        | frequency | value |
|------------|------------------|-----------|-------|
| 172.16.1.1 | 2019-04-01T10:02 |      1000 |    10 |
| 172.16.1.1 | 2019-04-01T10:02 |      2000 |    20 |
|            |                  |           |       |
| 172.16.1.1 | 2019-04-01T11:00 |      1000 |  null |
| 172.16.1.1 | 2019-04-01T11:00 |      2000 |  null |
|            |                  |           |       |
| 172.16.1.1 | 2019-04-01T12:02 |      1000 |    10 |
| 172.16.1.1 | 2019-04-01T12:02 |      2000 |    20 |

Мы попытались добавить еще одно правильное объединение в запрос, но у нас просто не может быть результата, который мы хотим. Частоты не определены в другом месте, поэтому для получения доступных частот мы могли бы select distinct частоты в таблице. БД - это PostgreSQL.

1 Ответ

1 голос
/ 02 апреля 2019

Используйте cross join для генерации строк и затем left join для ввода значений:

select d.ip, t.timestamp, f.frequency,  fv.value
from devices d cross join
     (select distinct timestamp from frequencyvalue) t cross join
     (select distinct frequency from frequencyvalue) f left join
     frequencyvalue fv
     on fv.device_ip = d.ip and
        fv.timestamp = t.timestamp and
        fv.frequency = f.frequency;
...