Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't this windowed expression result in a divide by zero error?

I came across this answer on Programming Puzzles & Code Golf. In it, the author uses the expression (though the answer has since been edited to use a different solution):

row_number()over(order by 1/0)

I would have expected the 1/0 to result in a divide by zero exception, but it doesn't.

When I asked the author on PPCG, they replied "because 1/0 is not being calculated. where exists(select 1/0) will have the same effect". This leaves me a bit nonplussed, because where exists(select 1) is valid syntax, but row_number()over(order by 1) is not. So why is the expression in the order by not calculated? The result of the expression is an integer, and an integer is not allowed in the order by. How does SQL Server handle the order by in that case? I assume the effect is the same as row_number()over(order by (SELECT NULL)), but if we give an expression, I'd expect that expression to be evaluated.

Coincidentally, if one uses something like:

SELECT  ROW_NUMBER() OVER ( ORDER BY A.x )
FROM    (
            SELECT  *
            ,       1 / 0 x
            FROM    master..spt_values
        ) A

Again, no divide by zero error is reported (when the x column is not selected, naturally). So why is this allowed when an integer is not?

like image 538
HoneyBadger Avatar asked Mar 11 '19 09:03

HoneyBadger


People also ask

How to eliminate divide by zero error in SQL?

We can modify our initial query using the SQL NULLIF statement. We place the following logic using NULLIF function for eliminating SQL divide by zero error: Use NULLIF function in the denominator with second argument value zero If the value of the first argument is also zero, this function returns a null value.

How to use NULLIF to avoid divide by zero error?

Initially, we use NULLIF function to avoid divide by zero error message. It accepts two arguments. Firstly, If both the arguments are equal, it returns a null value For example, suppose that the value of both arguments is 10. In this case, the output will be null.

Why can’t I Divide a number by zero?

Mathematically, this does not make any sense. You can’t divide a number by zero and expect a meaningful result. To deal with this error, we need to decide what should be returned when we try to divide by zero. For example, we might want a null value to be returned.

Why does the division function throw a runtime_error when passing denominators?

The Division function checks if the denominator passed is equal to zero if no it returns the quotient, if yes it throws a runtime_error exception. This Exception is caught by the catch block which prints the message “Exception occurred” and then calls the what function with runtime_error object e.


1 Answers

You're not allowed integer literals in this ORDER BY but you are allowed expressions returning integers - otherwise you wouldn't be able to use e.g. CASE expressions.

So that's why you're not allowed OVER (ORDER BY 1) but are apparently allowed OVER (ORDER BY 1/0). I don't think it's a deliberate feature to allow you to write this. You're certainly not allowed a divide by zero if your expression is actually dependent on any columns from the rows - this generates an error:

select name,object_id,ROW_NUMBER() OVER (ORDER BY 1/(object_id-3))
from sys.objects

So, I'd put it down to "the optimizer is smart enough to realise that this expression doesn't depend on any row values, therefore it's the same value for all rows so we do not need to compute it". In a sane language, this would generate a warning.

like image 177
Damien_The_Unbeliever Avatar answered Oct 13 '22 03:10

Damien_The_Unbeliever