有没有办法使用ClickHouse MV来计算特定时间范围的差异?

发布于 2025-02-06 13:40:02 字数 2106 浏览 2 评论 0原文

例如,这是我的源表,

CREATE TABLE IF NOT EXISTS market
(
    id          UInt64,
    price       DECIMAL128(18),
    create_time UInt64
) ENGINE = MergeTree()
      partition by toYYYYMM(FROM_UNIXTIME(create_time))
      order by create_time;

我想做的是创建一个MV,该MV异步计算出30分钟的价格差异。然后,我每次都可以使用id获得此MV的区别。这是一个SQL示例。直接执行它,它可以正常工作,但是在创建MV(为select ...)并从MV查询时不起作用。

select id,
       (t1.price - t2.price)                                  as price_delta,
       t2.price                                               as start_price,
       t1.price                                               as end_price,
       round(toFloat64(price_delta) / toFloat64(t2.price), 2) as price_delta_rate,
       now()                                                  as update_time
from (select id, price
      from market
      where create_time >= date_sub(MINUTE, 30, now())
      order by create_time desc
      limit 1) t1
         left join
     (select id, price
      from market
      where create_time >= date_sub(MINUTE, 30, now())
      order by create_time
      limit 1) t2
     ON t1.id = t2.id;

这是我创建MV的SQL

CREATE MATERIALIZED VIEW IF NOT EXISTS market_stats_30min
            ENGINE = ReplacingMergeTree()
                order by id
            POPULATE
AS
select id,
       (t1.price - t2.price)                                  as price_delta,
       t2.price                                               as start_price,
       t1.price                                               as end_price,
       round(toFloat64(price_delta) / toFloat64(t2.price), 2) as price_delta_rate,
       now()                                                  as update_time
from (select id, price
      from market
      where create_time >= date_sub(MINUTE, 30, now())
      order by create_time desc
      limit 1) t1
         left join
     (select id, price
      from market
      where create_time >= date_sub(MINUTE, 30, now())
      order by create_time
      limit 1) t2
     ON t1.id = t2.id;

For example, this is my source table

CREATE TABLE IF NOT EXISTS market
(
    id          UInt64,
    price       DECIMAL128(18),
    create_time UInt64
) ENGINE = MergeTree()
      partition by toYYYYMM(FROM_UNIXTIME(create_time))
      order by create_time;

What I want to do is to create a MV which asynchronously calculate the price difference whthin 30 min. And then, I can get the difference from this MV using an id every time. Here is an SQL example. It works correctly while directly execute it, but does not work while creating a MV(AS SELECT ...) and querying from the MV.

select id,
       (t1.price - t2.price)                                  as price_delta,
       t2.price                                               as start_price,
       t1.price                                               as end_price,
       round(toFloat64(price_delta) / toFloat64(t2.price), 2) as price_delta_rate,
       now()                                                  as update_time
from (select id, price
      from market
      where create_time >= date_sub(MINUTE, 30, now())
      order by create_time desc
      limit 1) t1
         left join
     (select id, price
      from market
      where create_time >= date_sub(MINUTE, 30, now())
      order by create_time
      limit 1) t2
     ON t1.id = t2.id;

Here is my SQL to create a MV

CREATE MATERIALIZED VIEW IF NOT EXISTS market_stats_30min
            ENGINE = ReplacingMergeTree()
                order by id
            POPULATE
AS
select id,
       (t1.price - t2.price)                                  as price_delta,
       t2.price                                               as start_price,
       t1.price                                               as end_price,
       round(toFloat64(price_delta) / toFloat64(t2.price), 2) as price_delta_rate,
       now()                                                  as update_time
from (select id, price
      from market
      where create_time >= date_sub(MINUTE, 30, now())
      order by create_time desc
      limit 1) t1
         left join
     (select id, price
      from market
      where create_time >= date_sub(MINUTE, 30, now())
      order by create_time
      limit 1) t2
     ON t1.id = t2.id;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

瀟灑尐姊 2025-02-13 13:40:02

物质视图只是在插入触发器之后,在您插入的新数据块中起作用
因此,您的插入市场在大多数情况下不包含所有必需的数据

填充重新计算完整表格以进行物质化的视图,只需

尝试在SELECT中使用窗口功能
https://clickhouse.com/docs/docs/en/sql-reference/sql-reference/window - 功能/,没有实现的视图

Materialized view is just after insert trigger which works inside new data block which you inserted
So, your INSERT INTO market doesn't contain all required data in most of the cases

POPULATE recalculate full table for materialized view just once

Try to use window functions in SELECT
https://clickhouse.com/docs/en/sql-reference/window-functions/, without materialized view

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文