2017-06-01 32 views
2

我們的任務是在ClickHouse中運行一批~20000個查詢並將結果存儲到CSV文件中。每個查詢都是返回單個數字的count()聚合。如何使ClickHouse count()函數在零匹配的情況下返回0?

我們這樣做是這樣的:

./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?

回答

1

我們設法以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]); 
    } 
    } 
}); 
0

這是ClickHouse的一個已知問題。 要解決該問題,請按照下列步驟操作。

假設你數查詢是這樣的:

SELECT count(*) AS count 
FROM mytable 

把你的查詢到這個SQL模板:

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

所以最終的查詢將是這樣的:

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

注意:使用中沒有性能開銷此解決方法。

相關問題