在 ClickHouse 中使用 Array(Tuple(LowCardinality(String), Int32))

Posted

技术标签:

【中文标题】在 ClickHouse 中使用 Array(Tuple(LowCardinality(String), Int32))【英文标题】:Using Array(Tuple(LowCardinality(String), Int32)) in ClickHouse 【发布时间】:2020-03-20 05:05:00 【问题描述】:

我有一张桌子

CREATE TABLE table (
    id Int32,
    values Array(Tuple(LowCardinality(String), Int32)),
    date Date
) ENGINE MergeTree()
PARTITION BY toYYYYMM(date)
ORDER BY (id, date)

但是在执行请求的时候

SELECT count(*)
FROM table
WHERE (arrayExists(x -> ((x.1) = toLowCardinality('pattern')), values) = 1)

我收到一个错误

Code: 49. DB::Exception: Received from clickhouse:9000. DB::Exception: Cannot capture column 3 because it has incompatible type: got String, but LowCardinality(String) is expected..

如果我替换列“值” 值数组(元组(字符串,Int32)) 然后请求被正确执行。

使用 Array(Tuple(LowCardinality(String), Int32)) 时会出现什么问题?

【问题讨论】:

看来是bug:github.com/ClickHouse/ClickHouse/issues/7815 【参考方案1】:

直到它被修复(见bug 7815),可以使用这个解决方法:

SELECT uniqExact((id, date)) AS count
FROM table
ARRAY JOIN values
WHERE values.1 = 'pattern'

对于有多个数组的情况,可以这样使用:

SELECT uniqExact((id, date)) AS count
FROM 
(
    SELECT 
        id, 
        date, 
        arrayJoin(values) AS v, 
        arrayJoin(values2) AS v2
    FROM table
    WHERE v.1 = 'pattern' AND v2.1 = 'pattern2'
)

【讨论】:

谢谢,但问题是我不能使用 ARRAY JOIN 两次来限制两个这样的字段【参考方案2】:

values Array(Tuple(LowCardinality(String), Int32)),

不要使用Tuple。它只会带来缺点。 它仍然是磁盘上的 *2 个文件。 它会减慢两倍,然后您只提取一个元组元素

https://gist.github.com/den-crane/f20a2dce94a2926a1e7cfec7cdd12f6d

valuesS Array(LowCardinality(String)),
valuesI Array(Int32)

【讨论】:

我使用 Tuple 来存储 Key-Value 值,并通过键值过滤,我使用值。存储在两个独立的数组中不适合我。 @ask125342 所有高阶函数都接受多个数组 select arrayFilter((v, k) -> k = 'a', values, keys) from (select ['a','a',' b','a'] 键,[1,2,3,4] 值)

以上是关于在 ClickHouse 中使用 Array(Tuple(LowCardinality(String), Int32))的主要内容,如果未能解决你的问题,请参考以下文章

Clickhouse的bitmap函数

大数据ClickHouse进阶:ClickHouse的Array Join子句

ClickHouse / Hive 数组交并差计算

ClickHouse : arrayMap, arrayJoin or ARRAY JOIN memory usage

ClickHouse:如何获取元组数组的 argMax

ClickHouse的近似值计算