在Snowflake中使用JSON时如何按数组中的标记进行过滤

时间:2017-09-27 06:23:21

标签: json snowflake-datawarehouse

我想存储数百万个时间序列,其中每个时间序列的每个时间点都标有任意一组标记。 看来我应该在Snowflake中使用带有标签的JSON数组:

CREATE TABLE timeseries (obj_id INT, ts DATE, tags VARIANT, val INT)
INSERT INTO timeseries (obj_id, ts, tags, val) VALUES (442243, '2017-01-01', parse_json('["red", "small", "cheap"]'), 1)
INSERT INTO timeseries (obj_id, ts, tags, val) VALUES (673124, '2017-01-01', parse_json('["red", "small", "expensive"]'), 2)
INSERT INTO timeseries (obj_id, ts, tags, val) VALUES (773235, '2017-01-01', parse_json('["black", "small", "cheap"]'), 3)

现在我希望看到标有"小"的所有时间序列的平均值。和"便宜",例如

SELECT ts, AVG(val)
FROM timeseries
WHERE "small" IN tags AND "cheap" IN tags
GROUP BY ts

会返回:

ts, avg(val)
2017-01-01, 2

实现它的正确Snowflake语法/架构/方法是什么? 请注意,我不希望FLATTEN爆炸行,我只想过滤掉所有不便宜的行。和'小'。

1 个答案:

答案 0 :(得分:1)

您可以直接使用数组类型,例如:

,而不是使用JSON
CREATE TABLE ts2 (obj_id INT, ts DATE, tags ARRAY, val INT);
INSERT INTO ts2 (obj_id, ts, tags, val) select 442243, '2017-01-01', ARRAY_CONSTRUCT('red', 'small', 'cheap'), 1;
INSERT INTO ts2 (obj_id, ts, tags, val) select 673124, '2017-02-01', ARRAY_CONSTRUCT('red', 'small', 'expensive'), 2;
INSERT INTO ts2 (obj_id, ts, tags, val) select 773235, '2017-01-01', ARRAY_CONSTRUCT('black', 'small', 'cheap'), 3;

VALUES子句不能使用ARRAY_CONSTRUCT等函数,但INSERT-SELECT可以使用。 (您也可以使用JSON和VARIANT类型执行此操作,但是您需要使用键名标记值,并在插入中使用PARSE_JSON。)

然后,要查询仅包含您选择的两个标记的行,请使用如下查询:

select 
  obj_id,
  tags
from ts2
where ARRAY_CONTAINS('small'::variant, tags)
  and ARRAY_CONTAINS('cheap'::variant, tags)
;