```
SELECT categoricalInformationValue(x.1, x.2) FROM (SELECT arrayJoin([(0, 0), (NULL, 2), (1, 0), (1, 1)]) AS x)
```
{
        const auto * y_col = static_cast<const ColumnUInt8 *>(columns[category_count]);
        bool y = y_col->getData()[row_num];
        for (size_t i : collections::range(0, category_count))
        {
            const auto * x_col = static_cast<const ColumnUInt8 *>(columns[i]);
            bool x = x_col->getData()[row_num];
            if (x)
                reinterpret_cast<T *>(place)[i * 2 + size_t(y)] += 1;
        }
        reinterpret_cast<T *>(place)[category_count * 2 + size_t(y)] += 1;
    }
    void merge(AggregateDataPtr __restrict place, ConstAggregateDataPtr rhs, Arena *) const override
    {
        for (size_t i : collections::range(0, category_count + 1))
        {
            reinterpret_cast<T *>(place)[i * 2] += reinterpret_cast<const T *>(rhs)[i * 2];
            reinterpret_cast<T *>(place)[i * 2 + 1] += reinterpret_cast<const T *>(rhs)[i * 2 + 1];
        }
    }
    void serialize(ConstAggregateDataPtr __restrict place, WriteBuffer & buf, std::optional<size_t> ) const override
    {
        buf.write(place, sizeOfData());
    }
    void deserialize(AggregateDataPtr __restrict place, ReadBuffer & buf, std::optional<size_t> , Arena *) const override
    {
        buf.read(place, sizeOfData());
    }
    DataTypePtr getReturnType() const override