```sql

CREATE MATERIALIZED VIEW player_champ_counts_mv
ENGINE = AggregatingMergeTree() ORDER BY (patch_num, my_account_id, champ_id)
as select patch_num, my_account_id, champ_id, countState() as c_state
from full_info
group by patch_num, my_account_id, champ_id;

create view player_champ_counts as
select patch_num, my_account_id, champ_id, countMerge(c_state) as c
from player_champ_counts_mv
group by patch_num, my_account_id, champ_id;
```

2.4s:
`select * from player_champ_counts`

900ms:
```
select patch_num, my_account_id, champ_id, countMerge(c_state) as c
from player_champ_counts_mv
group by patch_num, my_account_id, champ_id;
```

In other words, just inlining the definition of the view is doing something different than querying the view itself.
bool hasMoreThanOneStream() const { return getNumStreams() > 1; }
    bool hasTotals() const { return totals_having_port != nullptr; }
    const Block & getHeader() const { return current_header; }
    void addTableLock(const TableLockHolder & lock) { table_locks.push_back(lock); }
    void addInterpreterContext(std::shared_ptr<Context> context) { interpreter_context.emplace_back(std::move(context)); }
    void addStorageHolder(StoragePtr storage) { storage_holders.emplace_back(std::move(storage)); }
    
    void setProgressCallback(const ProgressCallback & callback);
    void setProcessListElement(QueryStatus * elem);
    
    size_t getNumThreads() const
    {
        auto num_threads = streams.maxParallelStreams();
        if (max_threads)
            num_threads = std::min(num_threads, max_threads);
        return std::max<size_t>(1, num_threads);
    }
    
    void setMaxThreads(size_t max_threads_) { max_threads = max_threads_; }
    
    Pipe getPipe() &&;
    Pipes getPipes() &&;
private: