Impacted versions:

8, 9, 10, master

Steps to reproduce:

Run `odoo shell --log-level=debug_sql` on a database where accounting is installed with demo data.

```
>>> AML = env['account.move.line']
>>> AML.search([('tax_ids.amount', '=', 15)])
```

You get the following trace of 4 sql statements:

The first one is ok:
```sql
SELECT "account_tax".id FROM "account_tax" WHERE (("account_tax"."active" = %s)  AND  ("account_tax"."amount" = %s)) ORDER BY "account_tax"."sequence"  
```

The second one can be improved and is discussed in https://github.com/odoo/odoo/pull/16066, it's not the point of this issue.
```sql
SELECT "account_move_line_id" FROM "account_move_line_account_tax_rel" WHERE "account_tax_id" IN %s
```

Then it does the same query twice with apparently no good reason (at least none I understand).
```sql
SELECT "account_move_line".id FROM "account_move_line" WHERE ("account_move_line"."id" in (%s)) ORDER BY "account_move_line"."date" DESC,"account_move_line"."id" DESC 
SELECT "account_move_line".id FROM "account_move_line" WHERE ("account_move_line"."id" in (%s)) ORDER BY "account_move_line"."date" DESC,"account_move_line"."id" DESC 
```

The problem has its source [here](https://github.com/odoo/odoo/blob/b8ce0db8e105ed3c9ab4aefe8bce5028764694f4/odoo/osv/expression.py#L879): at first glance I'd say lines 879 and 880 could be replaced with

```leaf.leaf = (path[0], 'in', right_ids)```
openerp/osv/expression.py
(not <term1>) and (<term2> or <term3>)
The second level of syntax deals with the term representation. A term
is a triple of the form (left, operator, right). That is, a term uses
an infix notation, and the available operators, and possible left and
right operands differ with those of the previous level. Here is a
possible term::
    ('company_id.name', '=', 'OpenERP')
The left and right operand don't have the same possible values. The
left operand is field name (related to the model for which the domain
applies).  Actually, the field name can use the dot-notation to
traverse relationships.  The right operand is a Python value whose
type should match the used operator and field type. In the above
example, a string is used because the name field of a company has type
string, and because we use the '=' operator. When appropriate, a 'in'
operator can be used, and thus the right operand should be a list.
Note: the non-uniform syntax could have been more uniform, but this
would hide an important limitation of the domain syntax. Say that the
term representation was ['=', 'company_id.name', 'OpenERP']. Used in a
complete domain, this would look like::
    ['!', ['=', 'company_id.name', 'OpenERP']]
and you would be tempted to believe something like this would be
possible::
    ['!', ['=', 'company_id.name', ['&', ..., ...]]]
That is, a domain could be a valid operand. But this is not the
case. A domain is really limited to a two-level nature, and can not
take a recursive form: a domain is not a valid second-level operand.
Unaccent - Accent-insensitive search
OpenERP will use the SQL function 'unaccent' when available for the
'ilike' and 'not ilike' operators, and enabled in the configuration.
Normally the 'unaccent' function is obtained from `the PostgreSQL