【问题标题】:Clickhouse ASOF left Join right table Nullable column is not implementedClickhouse ASOF left Join right table Nullable column 未实现
【发布时间】:2022-01-04 08:27:13
【问题描述】:

我试图在文档和其他论坛中找到答案,但未能理解。 文档:https://clickhouse.com/docs/en/sql-reference/statements/select/join/CH doc

我的表类似于:stack overflow question

我想在交易前获得订单价格(并返回订单 ts 和有关交易的信息)。

使用下面的代码,我得到以下错误:SQL 错误 [48]: ClickHouse 异常,代码:48,DB::Exception: ASOF join over right table Nullable column is not implemented

我尝试的是条件“IS NOT NULL”,但它没有做任何事情。

代码:

WITH 
orders as(
    SELECT order_timestamp, order_price, product_id
    FROM order_table
    WHERE
        ( order_timestamp >= toInt32(toDateTime64('2022-01-02 10:00:00.000', 3))*1000
            AND order_timestamp <= toInt32(toDateTime64('2022-01-02 12:00:00.000', 3))*1000)
        AND product_id = 'SPXFUT'
        AND order_timestamp IS NOT NULL),
trades as (
    SELECT 
       trade_timestamp,
       price
    FROM trades_table
    WHERE
         trade_timestamp >= toInt32(toDateTime64('2021-12-02 10:00:00.000', 3))*1000 AND trade_timestamp <= toInt32(toDateTime64('2021-12-02 12:00:00.000', 3))*1000
         AND product_id = 'SPXFUT'
         AND trade_timestamp IS NOT NULL),
results as(
SELECT 
    tt.product_id,
    tt.trade_timestamp,
    tt.price,
    o.order_timestamp,
    o.order_price
    FROM trades tt
    ASOF LEFT JOIN orders o
    ON (tt.product_id = o.product_id ) AND (tt.trade_timestamp >= o.order_timestamp ))
SELECT *
FROM results

【问题讨论】:

    标签: sql join clickhouse


    【解决方案1】:

    ASOF LEFT JOIN 的当前实现要求不等式中使用的右侧列是不可为空的类型。由于类型来自表定义(并且您的 order_table 必须具有 order_timestamp 的定义,如 Nullable(Int64)),ClickHouse 将拒绝运行,但出现 ClickHouse exception, code: 48,DB::Exception: ASOF join over right table Nullable column is not implemented 等异常。

    作为一种解决方案,您可以将 o.order_timestampassumeNotNull 函数包装在 ASOF LEFT JOIN 条件中:

    ON (tt.product_id = o.product_id ) AND (tt.trade_timestamp >= assumeNotNull(o.order_timestamp) ))
    

    但是您应该考虑assumeNotNull (documentation) 的行为 - 它会为类型(默认值)提供非空值,这可能会在 o.order_timestamp 为空的情况下给出错误结果( assumeNotNull 是特定于实现的,可能会带来更多问题 - assumeNotNull and friends)。

    另一种解决方案是使用ifNull 并为缺失值提供合适的替换,避免assumeNotNull 带来的潜在问题:

    ON (tt.product_id = o.product_id ) AND (tt.trade_timestamp >= ifNull(o.order_timestamp,0) ))
    

    最后一个建议是将列数据类型更改为不可为空的:

    ALTER TABLE order_table MODIFY COLUMN order_timestamp <TypeName>;
    

    但这取决于您的用例 - 如果要求 order_timestamp 必须接受空值,我建议采用第二种解决方案。

    【讨论】:

    • 一个更可能的解决方案是使用子查询连接 ASOF LEFT JOIN (select ...., assumeNotNull(...) from orders where ... is not null) o假设NotNull 在这种情况下是安全的,因为我们使用 where 剪切空值。
    • 我已经测试了您的建议 Anselmo,它运行良好。感谢您的贡献。我相信“assumeNotNull()”不是问题,因为我在 WHERE 语句中指定了条件“非空”?丹尼·克兰,谢谢你的评论!我还没有尝试过这种方法,如果我尝试过,我会发布更新。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 2015-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-10
    相关资源
    最近更新 更多