右连接后根据包含空值的单行生成多行

Generate multiple rows based on a single row containing a null value after a right join

我有一个软件可以使用 SNMP 从多个设备检索数据。 然后,软件会在 table 中创建一条记录,其中包含开始轮询时间和结束轮询时间。

对于我们检索的每个 SNMP table,我们将数据放在不同的 table 中。

在下面的模型中,有一个 snmp table (FrequencyValue)。 table 是这样的:

| 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 |

当设备无法应答时就会出现问题,因为如 table FrequencyValue 所示,软件没有为该 table 创建记录。

问题: 为了绘制每个 frequencyvalue 的图形,我们想为每个 n 行创建 frequency 将有列 valuenull.

到目前为止,我们的查询如下所示:

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 table 中的频率。 数据库是 PostgreSQL。

使用 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;