如果匹配为零,如何使clickhouse count()函数返回0?

blpfk2vs  于 2021-07-15  发布在  ClickHouse
关注(0)|答案(3)|浏览(964)

我们的任务是在clickhouse中运行一批约20000个查询,并将结果存储到csv文件中。每个查询都是一个count()聚合,返回一个数字。
我们这样做:

./generate_queries.js | clickhouse-client --multiquery | tr '\n' ',' >> metrics.csv

(是的,后面的逗号,我们会解决的。)
查询示例:

SELECT count(*) FROM merged_data WHERE business_type = 22;

问题是,如果一个查询匹配零条记录,clickhouse只会返回零,并且结果csv文件中的记录数与查询数不同。
这可能是sql的标准行为,但我们如何解决这一问题,并使clickhouse count()在零匹配的情况下返回0?

yr9zkbsy

yr9zkbsy1#

现在你可以这样做:

SELECT
    count() - 1
FROM (
    SELECT
        business_type
    FROM
        merged_data
    WHERE
        business_type = 22
    UNION ALL
        toUInt64(1)
)

只要替换一下 toUInt64 不管是什么类型的 business_type 是。
开发人员已经意识到这个问题,并正在努力解决这个问题:https://github.com/yandex/clickhouse/issues/51https://groups.google.com/forum/#!topic/clickhouse/2js\u yzvyahm主题
目前的计划是增加一种从设置控制这种行为的能力。

esbemjvw

esbemjvw2#

我们用json输出格式解决了这个问题。

SELECT count(*) FROM merged_data WHERE business_type = 22 FORMAT JSONCompact;

本例中的db响应如下所示:

{
    "meta":
    [
        {
            "name": "count()",
            "type": "UInt64"
        }
    ],

    "data":
    [

    ],

    "rows": 0,

    "statistics":
    {
        "elapsed": 0.044646461,
        "rows_read": 53413865,
        "bytes_read": 53413865
    }
}

总是有一个响应,即使是在空匹配的情况下(我们看到 "rows": 0 如果是这样的话)。
json响应流解析器如下所示:

var readLine = require('readline');

var rl = readLine.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

var buf = '';

rl.on('line', line => {
  buf += line;

  if (line == '}') {
    // End of JSON => process.
    var json = JSON.parse(buf);
    buf = '';

    if (json.rows === 0) {
      console.log('0');
    }
    else {
      console.log(json.data[0][0]);
    }
  }
});
6tdlim6h

6tdlim6h3#

这是clickhouse的一个已知问题。要解决此问题,请执行以下步骤。
假设您的count查询是这样的:

SELECT count(*) AS count
FROM mytable

将查询放入此sql模板:

SELECT *
FROM 
(
    -- put your count query here 
    UNION ALL 
    SELECT toUInt64(0)
) 
LIMIT 1

最后的问题是:

SELECT *
FROM 
(
    SELECT count(*) AS count
    FROM mytable
    UNION ALL 
    SELECT toUInt64 (0)
) 
LIMIT 1

注意:使用此解决方案没有性能开销。

相关问题