(SQL) About parentheses in the WHERE clause

2

Hello, I have not found a lot of information in searches I've done on ... but I have a problem currently that is as follows:

I have a query with many simple conditions, just sequences of and . But today I needed to include some or , and behold the query simply can not finish, it runs for minutes until it stops because it exceeds the PostgresSQL memory limit or something. So I thought about separating those or within a block, in which case I put them in parentheses and then the query ran very quickly and brought me a result without errors. So I decided to do a test with another query, this time was much simpler and ... when I put the parentheses, the query now did not bring me anything else, but if I remove them, it executed as expected.

So I started to wonder, what was really going on and what is the correct procedure to do and how to use the parentheses in WHERE. Thank you in advance!

Example of the query I'm using without parentheses:

nfe.id_empresa = 4 and 
nfe.ano = '2016' and
nfe.id_empresa = nfe_item.id_empresa and
nfe.ano = nfe_item.ano and
nfe.mes = nfe_item.mes and
nfe_item.cst_icms = '010' or 
nfe_item.cst_icms = '030' or
nfe_item.cst_icms = '060' or
nfe_item.cst_icms = '070' or
nfe_item.cst_icms = '110' ;

Now with parentheses:

nfe.id_empresa = 4 and 
nfe.ano = '2016' and
nfe.id_empresa = nfe_item.id_empresa and
nfe.ano = nfe_item.ano and
nfe.mes = nfe_item.mes and
(
    nfe_item.cst_icms = '010' or 
    nfe_item.cst_icms = '030' or
    nfe_item.cst_icms = '060' or
    nfe_item.cst_icms = '070' or
    nfe_item.cst_icms = '110' 
);
    
asked by anonymous 18.05.2018 / 19:42

3 answers

4

Just as multiplication and division have precedence / priority over addition and subtraction, AND takes precedence / priority over OR .

That is, this:

nfe.id_empresa = 4 and 
nfe.ano = '2016' and
nfe.id_empresa = nfe_item.id_empresa and
nfe.ano = nfe_item.ano and
nfe.mes = nfe_item.mes and
nfe_item.cst_icms = '010' or 
nfe_item.cst_icms = '030' or
nfe_item.cst_icms = '060' or
nfe_item.cst_icms = '070' or
nfe_item.cst_icms = '110' ;

It's equivalent to this:

(
    nfe.id_empresa = 4 and 
    nfe.ano = '2016' and
    nfe.id_empresa = nfe_item.id_empresa and
    nfe.ano = nfe_item.ano and
    nfe.mes = nfe_item.mes and
    nfe_item.cst_icms = '010'
) or 
nfe_item.cst_icms = '030' or
nfe_item.cst_icms = '060' or
nfe_item.cst_icms = '070' or
nfe_item.cst_icms = '110' ;

And that's not what you want.

See more about precedence here .

In the form without parentheses, in cases where cst_icms is '030' , '060' , '070' or '110' , all records will be brought independently of the other fields ( id_empresa , ano , mes or anything on the nfe table). The result is a huge set of data, so it takes a long time.

Already in the second form with parentheses in or s, clauses with and will already have filtered a lot of results that would be wrong / unwanted before filtering by cst_icms .

    
18.05.2018 / 19:59
1

The parentheses causes PostgreSQL to treat all conditions grouped as a single thing, for example, in its first query, as the ORs are outside the parentheses, so if any cst_icms is equal to '030', ' 060 ',' 070 ', or' 110 ', will return those lines ignoring your other conditions, since one of your OR has been met.

Now in the second query, where you left your OR conditions grouped in parentheses, for a row to be returned you need to fulfill all the preceding conditions AND one of the conditions grouped by OR.

I hope to have been clear so far.

Now on the issue of popping DB query time, what may be happening is that as in your first query, without the parentheses, you are returning many results, enough that your database can not display all. Put a LIMIT 100, for example, in your first query and you will see that it has results, the problem is that they are many.

    
18.05.2018 / 20:00
1

It's just a matter of precedence of operators where" An operator at higher levels is evaluated before an operator at a lower level ".

In other words, the AND is processed before the OR.

true and false and true or true or false
[   false    ]
[          false      ] 
[               true          ]
[                   true               ] = true

Changing precedence, using parentheses:

true and false and (true or (true or false))
                             [    true    ]
                    [      true           ] 
         [            false               ]
[                   false                 ] = false
    
18.05.2018 / 20:05