Issue: Unwanted 'AS' when constructing HAVING clause
Author: desile
State: closed
Created: 2017-07-31 10:09:46

Hi!

When I use my peewee.Func object, which has _alias, in having(...), then Peewee adds keyword 'AS' in clause.

For example:
```
field = fn.Count(SystemUser.id).alias('roles_count')
query = query.having(field == 2)
```

Then I get syntax error:

> ...name" HAVING ((Count("t1"."id") AS roles_count...

I construct queries automatically from rest-requests, so I need to take fields from query.get_query_meta()[0] for comparing with requests and constructing query.

It is easy just clean _alias before constructing query and problem will go away, but nevertheless I think that it is strange behavior.

Thanks for attention!

Problem here https://github.com/coleifer/peewee/blob/master/peewee.py#L1741
Method `_parse_expression` calling `parse_node` , which adds 'AS'
```
            if node._alias:
                sql = ' '.join((sql, 'AS', node._alias))
```

What is the best way to correct it? Maybe using named argument in `parse_node` declaration?

Something like that:
```
    def _parse_expression(self, node, alias_map, conv):
        if isinstance(node.lhs, Field):
            conv = node.lhs
        lhs, lparams = self.parse_node(node.lhs, alias_map, conv, ignore_alias=True) #fix here
        rhs, rparams = self.parse_node(node.rhs, alias_map, conv, ignore_alias=True) #fix here
        if node.op == OP.IN and rhs == '()' and not rparams:
            return ('0 = 1' if node.flat else '(0 = 1)'), []
        template = '%s %s %s' if node.flat else '(%s %s %s)'
        sql = template % (lhs, self.get_op(node.op), rhs)
        return sql, lparams + rparams



    def parse_node(self, node, alias_map=None, conv=None, ignore_alias=False): #fix here
        sql, params, unknown = self._parse(node, alias_map, conv)
        if unknown and (conv is not None) and params:
            params = [conv.db_value(i) for i in params]

        if isinstance(node, Node):
            if node._negated:
                sql = 'NOT %s' % sql
            if node._alias and not ignore_alias: #fix here
                sql = ' '.join((sql, 'AS', node._alias))
            if node._ordering:
                sql = ' '.join((sql, node._ordering))

        if params and any(isinstance(p, Node) for p in params):
            clean_params = []
            clean_sql = []
            for idx, param in enumerate(params):
                if isinstance(param, Node):
                    csql, cparams = self.parse_node(param)

        return sql, params
```

Same problem with ORDER BY and probably with PARTITION BY and RANGE 

This "problem" has been present in peewee since at least version 2.0.0, and at present, exists in the 3.0 rewrite ([which you can see here](https://github.com/coleifer/peewee/tree/3.0a)).

The typical way to handle this is to either:

1. Store the unaliased SQL entity in a variable and only call `alias()` when you need to.
2. Use `SQL()` object to reference the alias directly.

Example 1:

```python
# Sort users by number of tweets composed, when that number is less than 10
count = fn.COUNT(Tweet.id)
query = (User
        .select(User, count.alias('tweet_count'))
        .join(Tweet, JOIN.LEFT_OUTER)
        .group_by(User)
        .having(count < 10)
        .order_by(count))
```

Example 2:

```python
# Sort users by number of tweets composed, when that number is less than 10
count = fn.COUNT(Tweet.id).alias('tweet_count')
count_ref = SQL('tweet_count')
query = (User
        .select(User, count.alias('tweet_count'))
        .join(Tweet, JOIN.LEFT_OUTER)
        .group_by(User)
        .having(count_ref < 10)
        .order_by(count_ref))
```

Thx for the help! `query.order_by(field.alias(None))` worked in my case

Oh... didn't even think about that way. I'll look at what would be involved implementing this in 3.0, the python->sql is much smarter and more flexible so should be do-able.

This is fixed by e88dbf5145261890bc1a55a2f24ce6dfba36d8db in the 3.0a branch.