我想存储数百万个时间序列,其中每个时间序列的每个时间点都标有任意一组标记。 看来我应该在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爆炸行,我只想过滤掉所有不便宜的行。和'小'。
答案 0 :(得分:1)
您可以直接使用数组类型,例如:
,而不是使用JSONCREATE 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)
;