Search code examples
arraysclickhouse

Clickhouse: sum of arrays based on another array


Say you have the following table:

ID  COUNTRIES                   UNITS
1   ['UK', 'Italy', 'France']   [2000, 1000, 1000]
1   ['France', 'Italy', 'UK']   [3000, 4000, 2000]
1   ['Italy']                   [2000]

Is there a way in ClickHouse to add up the RATIOS column for each country in the COUNTRIES column? Something like sum(UNITS) group by COUNTRIES

Expected result:

ID  COUNTRIES                   TOTAL_UNITS
1   ['UK', 'Italy', 'France']   [4000, 4000, 7000]

Reprex code:

SELECT data.1 ID, data.2 COUNTRIES, data.3 UNITS
FROM (
    SELECT arrayJoin([(1, ['UK', 'Italy', 'France'], [2000, 1000, 1000]), 
                    (1, ['France', 'Italy', 'UK'], [3000, 4000, 2000]), 
                    (1, ['Italy'], [2000])]) data);

Solution

  • select sumMap(COUNTRIES, UNITS) from (
    
    SELECT data.1 ID, data.2 COUNTRIES, data.3 UNITS
    FROM (
        SELECT arrayJoin([(1, ['UK', 'Italy', 'France'], [2000, 1000, 1000]), 
                        (1, ['France', 'Italy', 'UK'], [3000, 4000, 2000]), 
                        (1, ['Italy'], [2000])]) data)
    
    )
    
    ┌─sumMap(COUNTRIES, UNITS)───────────────────┐
    │ (['France','Italy','UK'],[4000,7000,4000]) │
    └────────────────────────────────────────────┘
    
    
    
    
    select (sumMap(COUNTRIES, UNITS) as x).1 a , x.2  b from (
    
    SELECT data.1 ID, data.2 COUNTRIES, data.3 UNITS
    FROM (
        SELECT arrayJoin([(1, ['UK', 'Italy', 'France'], [2000, 1000, 1000]), 
                        (1, ['France', 'Italy', 'UK'], [3000, 4000, 2000]), 
                        (1, ['Italy'], [2000])]) data)
    
    )
    ┌─a───────────────────────┬─b────────────────┐
    │ ['France','Italy','UK'] │ [4000,7000,4000] │
    └─────────────────────────┴──────────────────┘
    
    
    
    
    select groupArray(COUNTRY) COUNTRIES, groupArray(s) UNITS from (
    select sum(UNIT) s, COUNTRY from (
    
    SELECT data.1 ID, data.2 COUNTRIES, data.3 UNITS
    FROM (
        SELECT arrayJoin([(1, ['UK', 'Italy', 'France'], [2000, 1000, 1000]), 
                        (1, ['France', 'Italy', 'UK'], [3000, 4000, 2000]), 
                        (1, ['Italy'], [2000])]) data)
    ) array join UNITS as UNIT, COUNTRIES as COUNTRY
    group by COUNTRY)
    
    ┌─COUNTRIES───────────────┬─UNITS────────────┐
    │ ['France','Italy','UK'] │ [4000,7000,4000] │
    └─────────────────────────┴──────────────────┘