Вложенная карта Clickhouse: укажите общее количество - PullRequest
0 голосов
/ 31 января 2020

Таблица Clickhouse с вложенной картой:

CREATE TABLE IF NOT EXISTS Test.NestedTest2
(
    -- slices
    idx1 UInt8, -- just some index 1
    idx2 UInt8, -- just some index 2

    -- metrics
    totalCnt UInt64,  -- total http response count
    codeMap Nested(
        key UInt16,   -- http response code
        value UInt64  -- http response count
    )

) Engine MergeTree()
PARTITION BY (idx1)
ORDER BY (idx1, idx2)


INSERT INTO Test.NestedTest2 (idx1, idx2, totalCnt, codeMap.key, codeMap.value) 
VALUES 
    (1, 1, 5, array(200), array(5))
    (1, 1, 5, array(204), array(5))
    (1, 1, 15, array(404, 502), array(5, 10))
    (1, 2, 45, array(404, 502), array(20, 25))
    (2, 1, 20, array(404, 502, 200), array(5, 5, 10))

Где totalCnt только в качестве примера. Точно так же это может быть связано с общим значением, таким как memoryUsage.

Мне нужно получить конкретный c код ответа в общем количестве ответов в том же выборе:

-- where idx1 = 1
/*
┌─code─┬─count─┬─totalCnt─┐
│  200 │     5 │       70 │
│  204 │     5 │       70 │
│  404 │    25 │       70 │
│  502 │    35 │       70 │
└──────┴───────┴──────────┘
*/

Ответы [ 2 ]

1 голос
/ 31 января 2020
SELECT
    idx1,
    (arrayJoin(arrayMap((x, y) -> (x, y), (sumMap(codeMap.key, codeMap.value) AS a).1, a.2)) AS arr).1 AS code,
    arr.2 AS cnt,
    sum(totalCnt) AS total
FROM Test.NestedTest2
WHERE idx1 = 1
GROUP BY idx1

┌─idx1─┬─code─┬─cnt─┬─total─┐
│    1 │  200 │   5 │    70 │
│    1 │  204 │   5 │    70 │
│    1 │  404 │  25 │    70 │
│    1 │  502 │  35 │    70 │
└──────┴──────┴─────┴───────┘

Кстати, вы можете рассчитать total из codeMap.value - arrayReduce('sum', groupArrayArray

SELECT
    idx1,
    (arrayJoin(arrayMap((x, y) -> (x, y), (sumMap(codeMap.key, codeMap.value) AS a).1, a.2)) AS arr).1 AS code,
    arr.2 AS cnt,
    arrayReduce('sum', groupArrayArray(codeMap.value)) AS total
FROM Test.NestedTest2
WHERE idx1 = 1
GROUP BY idx1

┌─idx1─┬─code─┬─cnt─┬─total─┐
│    1 │  200 │   5 │    70 │
│    1 │  204 │   5 │    70 │
│    1 │  404 │  25 │    70 │
│    1 │  502 │  35 │    70 │
└──────┴──────┴─────┴───────┘
0 голосов
/ 31 января 2020

Этот способ не идеален из-за ARRAY JOIN (графические объявления c фильтры не работают с такими запросами).

SELECT idx1, code, val, total
FROM (

    SELECT
        idx1,
        sumMap(codeMap.key, codeMap.value) as arr,
        sum(totalCnt) as total
    FROM Test.NestedTest2
    WHERE idx1 = 1
    GROUP BY idx1

)
ARRAY JOIN arr.1 as code, arr.2 as val
ORDER BY idx1, code
/*
┌─idx1─┬─code─┬─val─┬─total─┐
│    1 │  200 │   5 │    70 │
│    1 │  204 │   5 │    70 │
│    1 │  404 │  25 │    70 │
│    1 │  502 │  35 │    70 │
└──────┴──────┴─────┴───────┘
*/
...