CREATE TABLE ... **EMPTY** AS SELECT

**Use case**

Create a table with the same structure as SELECT query returns but don't fill it.

**Describe alternatives you've considered**

CREATE TABLE ... AS DESCRIBE (SELECT ...)

\- more consistent but also more clunky.
ASTSelectWithUnionQuery * select = nullptr;
    IAST * comment = nullptr;
    ASTTableOverrideList * table_overrides = nullptr; 
    bool is_dictionary{false}; 
    ASTExpressionList * dictionary_attributes_list = nullptr; 
    ASTDictionary * dictionary = nullptr; 
    std::optional<UInt64> live_view_timeout;    
    std::optional<UInt64> live_view_periodic_refresh;    
    bool is_watermark_strictly_ascending{false}; 
    bool is_watermark_ascending{false}; 
    bool is_watermark_bounded{false}; 
    bool allowed_lateness{false}; 
    bool attach_short_syntax{false};
    std::optional<String> attach_from_path = std::nullopt;
    bool replace_table{false};
    bool create_or_replace{false};
    
    String getID(char delim) const override { return (attach ? "AttachQuery" : "CreateQuery") + (delim + getDatabase()) + delim + getTable(); }
    ASTPtr clone() const override;
    ASTPtr getRewrittenASTWithoutOnCluster(const WithoutOnClusterASTRewriteParams & params) const override
    {
        return removeOnCluster<ASTCreateQuery>(clone(), params.default_database);
    }
    bool isView() const { return is_ordinary_view || is_materialized_view || is_live_view || is_window_view; }
    virtual QueryKind getQueryKind() const override { return QueryKind::Create; }
protected:
    void formatQueryImpl(const FormatSettings & settings, FormatState & state, FormatStateStacked frame) const override;
};
}