我希望在指定分区的一行中拥有一列的第一个值和第二列的最后一个值。为此,我创建了这个查询:
SELECT DISTINCT
b.machine_id,
batch,
timestamp_sta,
timestamp_stp,
FIRST_VALUE(timestamp_sta) OVER w AS batch_start,
LAST_VALUE(timestamp_stp) OVER w AS batch_end
FROM db_data.sta_stp AS a
JOIN db_data.ll_lu AS b
ON a.ll_lu_id=b.id
WINDOW w AS (PARTITION BY batch, machine_id ORDER BY timestamp_sta)
ORDER BY timestamp_sta, batch, machine_id;
但正如您在图片中看到的那样,batch_end列中返回的数据不正确。
batch_start 列具有正确的 timestamp_sta 列的第一个值。但是 batch_end 应该是" 2012-09-17 10:49:45"它等于同一行的 timestamp_stp 。
为什么会这样?
答案 0 :(得分:6)
@ŁukaszKamiński给出的解释解决了问题的核心。
但是,googleImageButton.setOnClickListener(googleImageButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//action
}
});)
应替换为last_value
。您按max()
排序,因此最后一个值是timestamp_sta
最大的值,可能与timestamp_sta
有关,也可能与timestamp_stp
无关。我也会按这两个字段排序。
SELECT DISTINCT
b.machine_id,
batch,
timestamp_sta,
timestamp_stp,
FIRST_VALUE(timestamp_sta) OVER w AS batch_start,
MAX(timestamp_stp) OVER w AS batch_end
FROM db_data.sta_stp AS a
JOIN db_data.ll_lu AS b
ON a.ll_lu_id=b.id
WINDOW w AS (PARTITION BY batch, machine_id
ORDER BY timestamp_sta,timestamp_stp
RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
ORDER BY timestamp_sta, batch, machine_id;
答案 1 :(得分:6)
这个问题很老,但是这个解决方案比到目前为止发布的解决方案更简单,更快捷:
SELECT b.machine_id
, batch
, timestamp_sta
, timestamp_stp
, min(timestamp_sta) OVER w AS batch_start
, max(timestamp_stp) OVER w AS batch_end
FROM db_data.sta_stp a
JOIN db_data.ll_lu b ON a.ll_lu_id = b.id
WINDOW w AS (PARTITION BY batch, b.machine_id) -- No ORDER BY !
ORDER BY timestamp_sta, batch, machine_id; -- why this ORDER BY?
如果将 ORDER BY
添加到窗口框架定义中,则每个带有较大的ORDER BY
表达式的下一行将以更高的帧开始。 min()
和first_value()
都无法返回整个分区的“第一个”时间戳。没有ORDER BY
,同一分区的所有行都是 peers ,您将获得所需的结果。
您添加的ORDER BY
有效(不是窗口框架定义中的一个,外部的),但是似乎没有任何意义,并且使查询更昂贵。您可能应该使用与您的窗口框架定义一致的ORDER BY
子句,以避免额外的排序费用:
...
ORDER BY batch, b.machine_id, timestamp_sta, timestamp_stp
在此查询中,我看不到需要DISTINCT
。您可以根据需要添加它。或DISTINCT ON ()
。但是ORDER BY
子句变得更加重要。参见:
如果您需要同一行中的其他一些列(同时仍按时间戳进行排序),则可以使用FIRST_VALUE()
和LAST_VALUE()
来实现。您可能需要将此附加到窗口框架定义 then :
ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
请参阅:
答案 2 :(得分:3)
frame_clause指定构成窗口框架的行集,它是当前分区的子集,用于那些作用于框架而不是整个分区的窗口函数。帧可以在RANGE或ROWS模式下指定;在任何一种情况下,它都从frame_start运行到frame_end。 如果省略frame_end,则默认为CURRENT ROW 。
UNBOUNDED PRECEDING的frame_start意味着框架以分区的第一行开始,同样,UNBOUNDED FOLLOWING的frame_end意味着框架以分区的最后一行结束。
last_value(value any)返回在窗口框架的最后一行
的行评估的值
所以正确的SQL应该是:
SELECT DISTINCT
b.machine_id,
batch,
timestamp_sta,
timestamp_stp,
FIRST_VALUE(timestamp_sta) OVER w AS batch_start,
LAST_VALUE(timestamp_stp) OVER w AS batch_end
FROM db_data.sta_stp AS a
JOIN db_data.ll_lu AS b
ON a.ll_lu_id=b.id
WINDOW w AS (PARTITION BY batch, machine_id ORDER BY timestamp_sta range between unbounded preceding and unbounded following)
ORDER BY timestamp_sta, batch, machine_id;