我正在使用Vertica,这让我无法使用CROSS APPLY。显然,Vertica中没有CTE这样的东西。
这就是我所拥有的:
t:
day | id | metric | d_metric
-----------+----+--------+----------
2011-12-01 | 1 | 10 | 10
2011-12-03 | 1 | 12 | 2
2011-12-04 | 1 | 15 | 3
请注意,在第一天,delta等于指标值。 我想填补空白,如下:
t_fill:
day | id | metric | d_metric
-----------+----+--------+----------
2011-12-01 | 1 | 10 | 10
2011-12-02 | 1 | 10 | 0 -- a delta of 0
2011-12-03 | 1 | 12 | 2
2011-12-04 | 1 | 15 | 3
我想到了一种日复一日的方法,但我真正喜欢的是一种可以一次性运行的解决方案。
我认为我可以使用LAST_VALUE,但我无法提出正确的JOIN语句,这些语句可以让我对每个id的日常历史进行正确的分区和排序。
编辑: 假设我有一个这样的表:
calendar:
day
------------
2011-01-01
2011-01-02
...
可以参与联接。我的意图是将日期范围维持在日历以匹配 t 中的日期范围。
编辑: 关于我正在寻找什么的更多注释,只是为了具体:
在生成 t_fill 时,我想完全涵盖 t 中的日期范围,以及两者之间缺少的日期范围。因此,正确的 t_fill 将在同一日期开始,并在与 t 相同的日期结束。 t_fill 有两个属性:
1)一旦id出现在某个日期,每个日期都会有一行。这是原始问题中隐含的填补空白。
2)如果没有行为一个id以后再一些日期之后出现,在 t_fill 溶液应该欢快产生从最后的数据点的日期与相同量度值的行(和0 DELTA)截至 t 的结束日期。
解决方案可能会将早期日期回填到 t 中日期范围的开头。也就是说,对于 t 中第一个日期之后显示的任何ID, t 中的第一个日期与ID的第一个日期之间的行将使用metric = 0填充和d_metric = 0。我不喜欢这种解决方案,因为它对于进入系统的每个id都有更高的增长因子。但我可以轻松地通过在新表中选择公式!= 0和d_metric!= 0的行来处理它。
答案 0 :(得分:1)
这是关于Jonathan Leffler提出的建议,而是关于老式的低级 SQL(没有花哨的CTE或窗口函数或聚合子查询):
SET search_path='tmp'
DROP TABLE ttable CASCADE;
CREATE TABLE ttable
( zday date NOT NULL
, id INTEGER NOT NULL
, metric INTEGER NOT NULL
, d_metric INTEGER NOT NULL
, PRIMARY KEY (id,zday)
);
INSERT INTO ttable(zday,id,metric,d_metric) VALUES
('2011-12-01',1,10,10)
,('2011-12-03',1,12,2)
,('2011-12-04',1,15,3)
;
DROP TABLE ctable CASCADE;
CREATE TABLE ctable
( zday date NOT NULL
, PRIMARY KEY (zday)
);
INSERT INTO ctable(zday) VALUES
('2011-12-01')
,('2011-12-02')
,('2011-12-03')
,('2011-12-04')
;
CREATE VIEW v_cte AS (
SELECT t.zday,t.id,t.metric,t.d_metric
FROM ttable t
JOIN ctable c ON c.zday = t.zday
UNION
SELECT c.zday,t.id,t.metric, 0
FROM ctable c, ttable t
WHERE t.zday < c.zday
AND NOT EXISTS ( SELECT *
FROM ttable nx
WHERE nx.id = t.id
AND nx.zday = c.zday
)
AND NOT EXISTS ( SELECT *
FROM ttable nx
WHERE nx.id = t.id
AND nx.zday < c.zday
AND nx.zday > t.zday
)
)
;
SELECT * FROM v_cte;
结果:
zday | id | metric | d_metric
------------+----+--------+----------
2011-12-01 | 1 | 10 | 10
2011-12-02 | 1 | 10 | 0
2011-12-03 | 1 | 12 | 2
2011-12-04 | 1 | 15 | 3
(4 rows)
答案 1 :(得分:0)
我不是Vertica用户,但如果您不想使用他们对GAP填充的原生支持,here您可以找到更通用的SQL解决方案。
答案 2 :(得分:0)
如果你想使用类似CTE的东西,那么如何使用临时表?实质上,CTE是特定查询的视图。
根据您的需要,您可以进行临时表事务或会话范围。
我仍然很想知道为什么使用常量插值填充间隙在这里不起作用。
答案 3 :(得分:0)
鉴于完整的日历表,它是可行的,但并非完全无关紧要。如果没有日历表,那将会更加困难。
您的查询需要适度准确地说明,这通常是“如何编写查询”的任何问题的一半。我想你正在寻找:
这为您提供了包含指标的完整日期列表。
然后,您需要自动加入该列表的两个副本,并将日期分开一天以形成增量。
请注意,如果某些ID值未显示在日期范围的开头,则不会显示。
以此作为指导,你应该能够开始,我相信。