这是本节的多页打印视图。
点击此处打印.
返回本页常规视图.
事件序列联接
事件序列联接是一个 Vertica SQL 扩展,它可以在两个系列的度量间隔并不完全一致(例如时间戳不匹配)时分析这两个系列。您可以直接比较两个系列的值,而不是将系列都标准化为相同的度量间隔。
事件序列联接是 外联接 的扩展,但它不会在存在不匹配时用 NULL 值填充非保留侧,而是用根据以前值获得的插值填充非保留侧。
编写常规联接与事件序列联接的不同之处在于 ON 子句中使用的 INTERPOLATE 谓词。例如,以下两个语句就说明了这一不同之处,更多详情请参阅编写事件系列联接。
与常规联接类似,事件序列联接具有内部和外部联接模式,这在之后的主题中会进行介绍。
有关完整的语法(包括注释和限制)请参阅 INTERPOLATE
1 - 事件系列联接示例的示例架构
如果您不打算运行查询,只想查看示例,则可以跳过此主题,直接转至编写事件系列联接。
hTicks 表和 aTicks 表的架构
后面的示例使用以下 hTicks 表和 aTicks 表的架构:
尽管 TIMESTAMP 更常用于事件序列列,但为了让输出更简单,此主题中的示例使用了 TIME。
这两个表的输出:
显示出间隙的示例查询
完全外部联接显示了时间戳中的间隙:
=> SELECT * FROM hTicks h FULL OUTER JOIN aTicks a ON h.time = a.time;
stock | time | price | stock | time | price
-------+----------+-------+-------+----------+--------
HPQ | 12:00:00 | 50.00 | ACME | 12:00:00 | 340.00
HPQ | 12:01:00 | 51.00 | | |
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 333.80
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 340.20
HPQ | 12:06:00 | 52.00 | | |
| | | ACME | 12:03:00 | 340.10
(6 rows)
Bid 表和 Asks 表的架构
后面的示例使用以下 hTicks 表和 aTicks 表。
这两个表的输出:
显示出间隙的示例查询
完全外部联接显示了时间戳中的间隙:
=> SELECT * FROM bid b FULL OUTER JOIN ask a ON b.time = a.time;
stock | time | price | stock | time | price
-------+----------+--------+-------+----------+--------
HPQ | 12:00:00 | 100.10 | ACME | 12:00:00 | 80.00
HPQ | 12:01:00 | 100.00 | HPQ | 12:01:00 | 101.00
ACME | 12:00:00 | 80.00 | ACME | 12:00:00 | 80.00
ACME | 12:03:00 | 79.80 | | |
ACME | 12:05:00 | 79.90 | | |
| | | ACME | 12:02:00 | 75.00
(6 rows)
2 - 编写事件系列联接
此主题中的示例包含时间戳不匹配项,就像在现实情形中可能会遇到的一样;例如,在没有交易时,股票在一段时间内可能会处于非活动状态,这时要想比较时间戳不匹配的两支股票会有一定挑战。
hTicks 表和 aTicks 表
如示例 ticks 架构所述,表 hTicks
在 12:02、12:03 和 12:04 缺少输入行,表 aTicks
在 12:01、12:02 和 12:04 缺少输入行。
通过全外联接查询事件系列
此查询使用传统的全外联接,在 hTicks 表和 aTicks 表之间找到了位于 12:00 和 12:05 的匹配项,然后用 NULL 值填充缺失的数据点。
=> SELECT * FROM hTicks h FULL OUTER JOIN aTicks a ON (h.time = a.time);
stock | time | price | stock | time | price
-------+----------+-------+-------+----------+--------
HPQ | 12:00:00 | 50.00 | ACME | 12:00:00 | 340.00
HPQ | 12:01:00 | 51.00 | | |
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 333.80
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 340.20
HPQ | 12:06:00 | 52.00 | | |
| | | ACME | 12:03:00 | 340.10
(6 rows)
要为缺失的数据点将空白替换为内插值,可使用 INTERPOLATE 谓词创建
事件序列联接。联接条件仅限于 ON 子句,该子句会在两个输入表的时间戳列中对等同谓词求值。换句话说,对于外表 hTicks 中的每个行,为内表 aTicks 中每个行的每个组合对 ON 子句谓词进行求值。
简单地重写全外联接可将 INTERPOLATE 谓词与所需的 PREVIOUS VALUE 关键字结合使用。请注意,对于事件序列数据,在事件序列数据上执行全外联接是最常见的场景,在此场景中,您可以同时保留两个表中的所有行。
=> SELECT * FROM hTicks h FULL OUTER JOIN aTicks a
ON (h.time INTERPOLATE PREVIOUS VALUE a.time);
Vertica 使用此表以前的值内插缺失数据(在全外联接中显示为 NULL):
![event series join](/images/hticks1.png)
注意
上面的输出顺序与普通全外联接不同,因为在数据系列数据中,对于每只股票(hTicks 和 aTicks),内插都是独立发生的,并且其中的数据根据等同谓词进行分区和排序。这意味着,内插发生在分区内部,而不是跨分区发生。
如果查看普通全外联接的输出,您可以发现这两个表在 12:00 和 12:05 时间列中存在一个匹配,但在 12:01,则不存在 ACME 的条目记录。因此,相关操作会根据 aTicks 表中以前的值为 ACME (ACME,12:00,340
) 内插一个值。
通过左外联接查询事件系列
您也可以使用左外联接和右外联接。例如,您可能决定仅保留 hTicks 的值。因此,您将写入左外联接:
=> SELECT * FROM hTicks h LEFT OUTER JOIN aTicks a
ON (h.time INTERPOLATE PREVIOUS VALUE a.time);
stock | time | price | stock | time | price
-------+----------+-------+-------+----------+--------
HPQ | 12:00:00 | 50.00 | ACME | 12:00:00 | 340.00
HPQ | 12:01:00 | 51.00 | ACME | 12:00:00 | 340.00
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 333.80
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 340.20
HPQ | 12:06:00 | 52.00 | ACME | 12:05:00 | 340.20
(5 rows)
以下数据与使用传统的左外联接得到的数据相似:
=> SELECT * FROM hTicks h LEFT OUTER JOIN aTicks a ON h.time = a.time;
stock | time | price | stock | time | price
-------+----------+-------+-------+----------+--------
HPQ | 12:00:00 | 50.00 | ACME | 12:00:00 | 340.00
HPQ | 12:01:00 | 51.00 | | |
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 333.80
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 340.20
HPQ | 12:06:00 | 52.00 | | |
(5 rows)
请注意,右外联接与保存表的行为相同,只是顺序相反。
通过内联接查询事件系列
请注意,如果忽视所有空白,INNER 事件序列联接的行为方式与普通的 ANSI SQL-99 联接相同。因此,这时不会内插任何内容,而且以下两个查询等效,都会返回相同的结果集。
普通的内联接:
=> SELECT * FROM HTicks h JOIN aTicks a
ON (h.time INTERPOLATE PREVIOUS VALUE a.time);
stock | time | price | stock | time | price
-------+----------+-------+-------+----------+--------
HPQ | 12:00:00 | 50.00 | ACME | 12:00:00 | 340.00
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 333.80
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 340.20
(3 rows)
事件序列内联接:
=> SELECT * FROM hTicks h INNER JOIN aTicks a ON (h.time = a.time);
stock | time | price | stock | time | price
-------+----------+-------+-------+----------+--------
HPQ | 12:00:00 | 50.00 | ACME | 12:00:00 | 340.00
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 333.80
HPQ | 12:05:00 | 51.00 | ACME | 12:05:00 | 340.20
(3 rows)
Bid 表和 Ask 表
使用 bid
表和 ask
表的示例架构,编写全外联接以内插缺失的数据点:
=> SELECT * FROM bid b FULL OUTER JOIN ask a
ON (b.stock = a.stock AND b.time INTERPOLATE PREVIOUS VALUE a.time);
在下列输出中,股票 HPQ 的第一行显示了 NULL,因为在 12:01 之前不存在 HPQ 的条目记录。
stock | time | price | stock | time | price
-------+----------+--------+-------+----------+--------
ACME | 12:00:00 | 80.00 | ACME | 12:00:00 | 80.00
ACME | 12:00:00 | 80.00 | ACME | 12:02:00 | 75.00
ACME | 12:03:00 | 79.80 | ACME | 12:02:00 | 75.00
ACME | 12:05:00 | 79.90 | ACME | 12:02:00 | 75.00
HPQ | 12:00:00 | 100.10 | | |
HPQ | 12:01:00 | 100.00 | HPQ | 12:01:00 | 101.00
(6 rows)
另外,请注意 ask
表的同一个行 (ACME,12:02,75
) 出现了三次。第一次出现是因为 bid
表中没有 ask
中的行,因此 Vertica 使用 12:02 的 ACME 值 (75.00) 插入了缺失值。第二次出现是因为 bid
中的行 (ACME,12:05,79.9
) 在 ask
中没有相应的匹配项。ask
中包含 (ACME,12:02,75
) 的行是最接近的行,因此使用它来插入值。
如果编写普通的全外联接,则可以发现哪些地方出现了不匹配的时间戳:
=> SELECT * FROM bid b FULL OUTER JOIN ask a ON (b.time = a.time);
stock | time | price | stock | time | price
-------+----------+--------+-------+----------+--------
ACME | 12:00:00 | 80.00 | ACME | 12:00:00 | 80.00
ACME | 12:03:00 | 79.80 | | |
ACME | 12:05:00 | 79.90 | | |
HPQ | 12:00:00 | 100.10 | ACME | 12:00:00 | 80.00
HPQ | 12:01:00 | 100.00 | HPQ | 12:01:00 | 101.00
| | | ACME | 12:02:00 | 75.00
(6 rows)