Vertica INTERPOLATE功能

时间:2013-06-12 16:23:00

标签: sql database vertica interpolation

Vertica的闪亮功能:

我有两个表格,我想加入 INTERPOLATE ,并希望第二个表格中的数据用最新的可用内容进行插值。但不幸的是,我无法得到我想要的结果。 我查看了与INTERPOLATE功能相关的Vertica文档,并尝试了一个工作正常的示例。

CREATE TABLE a
( family int,
  date DATE,
  id int
);

CREATE TABLE b
( Id int,
  date DATE,
  datapoint float
);

INSERT INTO a VALUES (1, '20130603', 1);
INSERT INTO a VALUES (1, '20130604', 1);
INSERT INTO a VALUES (1, '20130605', 1);
INSERT INTO a VALUES (1, '20130606', 1);
INSERT INTO a VALUES (1, '20130607', 1);

INSERT INTO b VALUES (1, '20130603', 3.00);

SELECT a.family, a.date, a.id, a.date, b.datapoint
  FROM a
  LEFT
  JOIN b
    ON a.id = b.id
   AND a.date INTERPOLATE PREVIOUS VALUE b.date;

vertdeva01:20130612-095628 > \g
 family |    date    | id |    date    | data
--------+------------+----+------------+------
      1 | 2013-06-03 |  1 | 2013-06-03 |    3
      1 | 2013-06-04 |  1 | 2013-06-04 |    3
      1 | 2013-06-05 |  1 | 2013-06-05 |    3
      1 | 2013-06-06 |  1 | 2013-06-06 |    3
      1 | 2013-06-07 |  1 | 2013-06-07 |    3

我得到了预期的结果。表 b 中的值根据表 a 中的日期进行插值。

但是当我尝试类似于稍微复杂的情况时,我并没有真正得到我想要的东西。

我打算实现的目标:

我打算通过 b a 中与 a 中的相应日期匹配的每个ID选择最新的可用数据>。因此,如果 a 具有(id,date)组合,那么我想从 b 获取该ID和日期的数据。但是如果该日期的b中没有该ID的数据,则获取该日期可用的 AS OF 。从 a 中获取截至日期有效的数据。换句话说,一种感觉回归的行为。只要在该日期之后该ID没有其他数据点,则id的数据点在 b 中有效。我希望这是有道理的。我知道使用MAX()GROUP BY执行此操作的方法。我想知道使用INTERPOLATE

是否可行

一个例子:

为了让你知道它是什么,我玩了一个例子。这次我只修改了以前创建的表以获得更多字段。

CREATE TABLE a
( family int,
  family_name varchar(50),
  industry varchar(15),
  style_flag varchar(1),
  id int,
  id_name varchar(50),
  id1 int,
  id2 int,
  id3 int,
  date DATE,
  id4 int
);

CREATE TABLE b
( id4 int,
  flag int,
  period int,
  date DATE,
 datapoint float
);

INSERT INTO a VALUES (1, '1family', 'comp', 'A', 1, '1 id', 101, 201, 301, '20130603', 401);
INSERT INTO a VALUES (1, '1family', 'comp', 'A', 2, '2 id', 102, 202, 302, '20130603', 402);
INSERT INTO a VALUES (1, '1family', 'comp', 'A', 3, '3 id', 103, 203, 303, '20130603', 403);

INSERT INTO a VALUES (2, '2family', 'bio', 'A', 5, '5 id', 105, 205, 305, '20130603', 405);
INSERT INTO a VALUES (2, '2family', 'bio', 'A', 7, '7 id', 107, 207, 307, '20130603', 407);
INSERT INTO a VALUES (2, '2family', 'bio', 'A', 9, '9 id', 109, 209, 309, '20130603', 409);

INSERT INTO b VALUES (401, 1, 10, '20130501', 2.00);
INSERT INTO b VALUES (401, 1, 20, '20130501', 1.50);
INSERT INTO b VALUES (401, 2, 10, '20130409', 12.34);
INSERT INTO b VALUES (401, 2, 20, '20130401', 10.56);

INSERT INTO b VALUES (402, 1, 10, '20130501', 2.00);
INSERT INTO b VALUES (402, 2, 20, '20130409', 12.34);
INSERT INTO b VALUES (402, 2, 20, '20130401', 10.56);
INSERT INTO b VALUES (402, 2, 20, '20130515', 20.55);

当我运行以下查询时:

SELECT a.family, a.family_name,       a.industry, a.style_flag,
       a.id, a.id_name,
       a.id1, a.id2, a.id3, a.date,
       b.id4, b.flag, b.period, b.datapoint
  FROM a
  LEFT
  JOIN b
    ON a.id4 = b.id4
   AND a.date INTERPOLATE PREVIOUS VALUE b.date;

我得到以下内容:

family | family_name | industry | style_flag | id | id_name | id1 | id2 | id3 |    date    | id4 | flag | period | datapoint
--------+-------------+----------+------------+----+---------+-----+-----+-----+------------+-----+------+--------+-----------
      2 | 2family     | bio      | A          |  5 | 5 id    | 105 | 205 | 305 | 2013-06-03 |     |      |        |
      1 | 1family     | comp     | A          |  1 | 1 id    | 101 | 201 | 301 | 2013-06-03 | 401 |    1 |     10 |         2
      1 | 1family     | comp     | A          |  3 | 3 id    | 103 | 203 | 303 | 2013-06-03 |     |      |        |
      2 | 2family     | bio      | A          |  9 | 9 id    | 109 | 209 | 309 | 2013-06-03 |     |      |        |
      2 | 2family     | bio      | A          |  7 | 7 id    | 107 | 207 | 307 | 2013-06-03 |     |      |        |
      1 | 1family     | comp     | A          |  2 | 2 id    | 102 | 202 | 302 | 2013-06-03 | 402 |    2 |     20 |     20.55

但是我需要从 b 中选择一个ID可用的最新值,用于(id4,flag,period)的一种组,而不是它当前给我的结果。 有没有办法可以使用 INTERPOLATE 功能?或者我应该采取完全不同的方法。 问题是表格中的数据 b 是稀疏的。我们可能每天都没有数据点,而 a 我们每天都有一个数据点。

我还尝试使用 TIMESERIES 子句和 TS_FIRST_VALUE(datapoint,'const')填补 b 中数据点之间的空白。但同样,与 a 中的ID日期相比, b 中id4,flag,period组合的最新日期可能会回溯。我最终遇到了与上面说明的相同的问题。

任何指导都将受到高度赞赏。

1 个答案:

答案 0 :(得分:1)

Eakan,

我没有访问Vertica环境来测试这个,但我认为你的第二个例子的问题是你的结果集只有一个日期,因为一个表中只有一个日期。但是有多个id4。因此,当您询问时,在您的查询中跨日期间隙进行插值时,插值没有间隙。您在b表的值中看到的间隙实际上是来自表中的不同id4值。

我不确定你是否可以在join子句中有多个插值但是如何:

SELECT     a.family, a.family_name, a.industry, a.style_flag, a.id, a.id_name,
           a.id1, a.id2, a.id3, a.date, a.id4, b.id4, b.flag, b.period, b.datapoint
FROM       a
LEFT JOIN  b
ON         a.id4 INTERPOLATE PREVIOUS VALUE b.id4 AND
           a.date INTERPOLATE PREVIOUS VALUE b.date;

我认为这会填充b表中的值,但这可能不是你想要的。也许你只是想对日期进行插值,并且你认为它不起作用只是因为你的表中没有多个日期。在表中添加几个日期,然后重新运行查询以查看我的意思。

如果您想更详细地讨论,请离线与我联系。如果您可以通过访问工作的Vertica环境来与我联系,那么我可以为您尝试更多的想法。

艾伦

关注:

好的,所以我设法访问了测试Vertica环境。

首先,您似乎不能拥有多个插值连接谓词...

vmartdb=> SELECT     a.family, a.family_name, a.industry, a.style_flag, a.id, a.id_name,
vmartdb->            a.id1, a.id2, a.id3, a.date, a.id4, b.id4, b.flag, b.period, b.datapoint
vmartdb-> FROM       est_cal.a AS a
vmartdb-> LEFT JOIN  est_cal.b AS b
vmartdb-> ON         a.id4 INTERPOLATE PREVIOUS VALUE b.id4 AND
vmartdb->            a.date INTERPOLATE PREVIOUS VALUE b.date;
ERROR 2093:  A join can have only one set of interpolated predicates
vmartdb=>

就是这样。

然后我尝试在表格中添加几个日期,看到你的原始查询确实插入了b表字段的间隙......

CREATE TABLE est_cal.a (
  family int,
  family_name varchar(50),
  industry varchar(15),
  style_flag varchar(1),
  id int,
  id_name varchar(50),
  id1 int,
  id2 int,
  id3 int,
  date DATE,
  id4 int
);

CREATE TABLE est_cal.b (
  id4 int,
  flag int,
  period int,
  date DATE,
 datapoint float
);

INSERT INTO est_cal.a VALUES (1, '1family', 'comp', 'A', 1, '1 id', 101, 201, 301, '20130603', 401);
INSERT INTO est_cal.a VALUES (1, '1family', 'comp', 'A', 2, '2 id', 102, 202, 302, '20130603', 402);
INSERT INTO est_cal.a VALUES (1, '1family', 'comp', 'A', 3, '3 id', 103, 203, 303, '20130603', 403);
INSERT INTO est_cal.a VALUES (2, '2family', 'bio', 'A', 5, '5 id', 105, 205, 305, '20130603', 405);
INSERT INTO est_cal.a VALUES (2, '2family', 'bio', 'A', 7, '7 id', 107, 207, 307, '20130603', 407);
INSERT INTO est_cal.a VALUES (2, '2family', 'bio', 'A', 9, '9 id', 109, 209, 309, '20130603', 409);
INSERT INTO est_cal.a VALUES (1, '1family', 'comp', 'A', 1, '1 id', 101, 201, 301, '20130604', 401);
INSERT INTO est_cal.a VALUES (1, '1family', 'comp', 'A', 2, '2 id', 102, 202, 302, '20130604', 402);
INSERT INTO est_cal.a VALUES (1, '1family', 'comp', 'A', 3, '3 id', 103, 203, 303, '20130604', 403);
INSERT INTO est_cal.a VALUES (2, '2family', 'bio', 'A', 5, '5 id', 105, 205, 305, '20130605', 405);
INSERT INTO est_cal.a VALUES (2, '2family', 'bio', 'A', 7, '7 id', 107, 207, 307, '20130605', 407);
INSERT INTO est_cal.a VALUES (2, '2family', 'bio', 'A', 9, '9 id', 109, 209, 309, '20130605', 409);
INSERT INTO est_cal.a VALUES (1, '1family', 'comp', 'A', 1, '1 id', 101, 201, 301, '20130605', 401);
INSERT INTO est_cal.a VALUES (1, '1family', 'comp', 'A', 2, '2 id', 102, 202, 302, '20130605', 402);
INSERT INTO est_cal.a VALUES (1, '1family', 'comp', 'A', 3, '3 id', 103, 203, 303, '20130605', 403);
INSERT INTO est_cal.a VALUES (2, '2family', 'bio', 'A', 5, '5 id', 105, 205, 305, '20130605', 405);
INSERT INTO est_cal.a VALUES (2, '2family', 'bio', 'A', 7, '7 id', 107, 207, 307, '20130605', 407);
INSERT INTO est_cal.a VALUES (2, '2family', 'bio', 'A', 9, '9 id', 109, 209, 309, '20130605', 409);

INSERT INTO est_cal.b VALUES (401, 1, 10, '20130501', 2.00);
INSERT INTO est_cal.b VALUES (401, 1, 20, '20130501', 1.50);
INSERT INTO est_cal.b VALUES (401, 2, 10, '20130409', 12.34);
INSERT INTO est_cal.b VALUES (401, 2, 20, '20130401', 10.56);
INSERT INTO est_cal.b VALUES (402, 1, 10, '20130501', 2.00);
INSERT INTO est_cal.b VALUES (402, 2, 20, '20130409', 12.34);
INSERT INTO est_cal.b VALUES (402, 2, 20, '20130401', 10.56);
INSERT INTO est_cal.b VALUES (402, 2, 20, '20130515', 20.55);


SELECT     a.family, a.family_name, a.industry, a.style_flag, a.id, a.id_name,
           a.id1, a.id2, a.id3, a.date AS a_date, b.date AS b_date, a.id4 AS a_id4, b.id4 AS b_id4, b.flag, b.period, b.datapoint
FROM       est_cal.a AS a
LEFT JOIN  est_cal.b AS b
ON         a.id4 = b.id4 AND
           a.date INTERPOLATE PREVIOUS VALUE b.date;

这产生了以下结果......

family | family_name | industry | style_flag | id | id_name | id1 | id2 | id3 |   a_date   |   b_date   | a_id4 | b_id4 | flag | period | datapoint
--------+-------------+----------+------------+----+---------+-----+-----+-----+------------+------------+-------+-------+------+--------+-----------
      2 | 2family     | bio      | A          |  7 | 7 id    | 107 | 207 | 307 | 2013-06-03 |            |   407 |       |      |        |
      2 | 2family     | bio      | A          |  7 | 7 id    | 107 | 207 | 307 | 2013-06-04 |            |   407 |       |      |        |
      2 | 2family     | bio      | A          |  7 | 7 id    | 107 | 207 | 307 | 2013-06-05 |            |   407 |       |      |        |
      2 | 2family     | bio      | A          |  7 | 7 id    | 107 | 207 | 307 | 2013-06-05 |            |   407 |       |      |        |
      2 | 2family     | bio      | A          |  5 | 5 id    | 105 | 205 | 305 | 2013-06-03 |            |   405 |       |      |        |
      2 | 2family     | bio      | A          |  5 | 5 id    | 105 | 205 | 305 | 2013-06-04 |            |   405 |       |      |        |
      2 | 2family     | bio      | A          |  5 | 5 id    | 105 | 205 | 305 | 2013-06-05 |            |   405 |       |      |        |
      2 | 2family     | bio      | A          |  5 | 5 id    | 105 | 205 | 305 | 2013-06-05 |            |   405 |       |      |        |
      2 | 2family     | bio      | A          |  9 | 9 id    | 109 | 209 | 309 | 2013-06-03 |            |   409 |       |      |        |
      2 | 2family     | bio      | A          |  9 | 9 id    | 109 | 209 | 309 | 2013-06-04 |            |   409 |       |      |        |
      2 | 2family     | bio      | A          |  9 | 9 id    | 109 | 209 | 309 | 2013-06-05 |            |   409 |       |      |        |
      2 | 2family     | bio      | A          |  9 | 9 id    | 109 | 209 | 309 | 2013-06-05 |            |   409 |       |      |        |
      1 | 1family     | comp     | A          |  1 | 1 id    | 101 | 201 | 301 | 2013-06-03 | 2013-05-01 |   401 |   401 |    1 |     10 |         2
      1 | 1family     | comp     | A          |  1 | 1 id    | 101 | 201 | 301 | 2013-06-04 | 2013-05-01 |   401 |   401 |    1 |     10 |         2
      1 | 1family     | comp     | A          |  1 | 1 id    | 101 | 201 | 301 | 2013-06-05 | 2013-05-01 |   401 |   401 |    1 |     10 |         2
      1 | 1family     | comp     | A          |  3 | 3 id    | 103 | 203 | 303 | 2013-06-03 |            |   403 |       |      |        |
      1 | 1family     | comp     | A          |  3 | 3 id    | 103 | 203 | 303 | 2013-06-04 |            |   403 |       |      |        |
      1 | 1family     | comp     | A          |  3 | 3 id    | 103 | 203 | 303 | 2013-06-05 |            |   403 |       |      |        |
      1 | 1family     | comp     | A          |  2 | 2 id    | 102 | 202 | 302 | 2013-06-03 | 2013-05-15 |   402 |   402 |    2 |     20 |     20.55
      1 | 1family     | comp     | A          |  2 | 2 id    | 102 | 202 | 302 | 2013-06-04 | 2013-05-15 |   402 |   402 |    2 |     20 |     20.55
      1 | 1family     | comp     | A          |  2 | 2 id    | 102 | 202 | 302 | 2013-06-05 | 2013-05-15 |   402 |   402 |    2 |     20 |     20.55
(21 rows)

因此,这表明日期插值正常工作。

艾伦