4

我们的任务是在 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?

4

3 回答 3

3

现在你可以这样做:

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/51 https://groups.google.com/forum/#!topic/clickhouse/2JS_yzvYAHM

当前的计划是添加一种从设置中控制此行为的功能。

于 2017-07-17T14:42:12.517 回答
1

我们设法使用 JSON 输出格式来解决这个问题。

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

在这种情况下,数据库响应如下所示:

{
    "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]);
    }
  }
});
于 2017-06-02T08:40:03.523 回答
0

这是 ClickHouse 的一个已知问题。要解决此问题,请按照下列步骤操作。

假设您的计数查询是这样的:

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

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

于 2017-08-26T10:48:44.033 回答