Repository: tobymao/sqlglot

Issue:
SQL optimize error when simpify expression with chaining div operations
```python
from sqlglot.executor import execute

tables = {
    "orders": [
        {"id": 1, "user_id": 100},
    ],
}

table = execute(
    """
    SELECT
      user_id * 0.5 / 10 / (2.0+3) from orders
    """,
    tables=tables
)

print(table)
```

Gets 25.0 as return while 1.0 is expected. The simplify rule replace the expression to user_id * 0.5 / 2, which is not equivalence

![optimizer py 2023-12-06 21-50-01](https://github.com/tobymao/sqlglot/assets/1175306/7defea7e-10ce-40f3-92eb-eea133de13d2)



Discussion:
Nice catch! This seems like a bug, indeed. I can take a look into this soon.

Resolving patch:
diff --git a/sqlglot/expressions.py b/sqlglot/expressions.py
--- a/sqlglot/expressions.py
+++ b/sqlglot/expressions.py
@@ -485,7 +485,7 @@ def unnest_operands(self):
 
     def flatten(self, unnest=True):
         """
-        Returns a generator which yields child nodes who's parents are the same class.
+        Returns a generator which yields child nodes whose parents are the same class.
 
         A AND B AND C -> [A, B, C]
         """
diff --git a/sqlglot/optimizer/simplify.py b/sqlglot/optimizer/simplify.py
--- a/sqlglot/optimizer/simplify.py
+++ b/sqlglot/optimizer/simplify.py
@@ -533,22 +533,24 @@ def _simplify_binary(expression, a, b):
         return exp.null()
 
     if a.is_number and b.is_number:
-        a = int(a.name) if a.is_int else Decimal(a.name)
-        b = int(b.name) if b.is_int else Decimal(b.name)
+        num_a = int(a.name) if a.is_int else Decimal(a.name)
+        num_b = int(b.name) if b.is_int else Decimal(b.name)
 
         if isinstance(expression, exp.Add):
-            return exp.Literal.number(a + b)
-        if isinstance(expression, exp.Sub):
-            return exp.Literal.number(a - b)
+            return exp.Literal.number(num_a + num_b)
         if isinstance(expression, exp.Mul):
-            return exp.Literal.number(a * b)
+            return exp.Literal.number(num_a * num_b)
+
+        # We only simplify Sub, Div if a and b have the same parent because they're not associative
+        if isinstance(expression, exp.Sub):
+            return exp.Literal.number(num_a - num_b) if a.parent is b.parent else None
         if isinstance(expression, exp.Div):
             # engines have differing int div behavior so intdiv is not safe
-            if isinstance(a, int) and isinstance(b, int):
+            if (isinstance(num_a, int) and isinstance(num_b, int)) or a.parent is not b.parent:
                 return None
-            return exp.Literal.number(a / b)
+            return exp.Literal.number(num_a / num_b)
 
-        boolean = eval_boolean(expression, a, b)
+        boolean = eval_boolean(expression, num_a, num_b)
 
         if boolean:
             return boolean


Test patch:
diff --git a/tests/fixtures/optimizer/simplify.sql b/tests/fixtures/optimizer/simplify.sql
--- a/tests/fixtures/optimizer/simplify.sql
+++ b/tests/fixtures/optimizer/simplify.sql
@@ -363,6 +363,15 @@ x * (1 - y);
 (1.0 * 3) * 4 - 2 * (5 / 2);
 12.0 - 2 * (5 / 2);
 
+a * 0.5 / 10 / (2.0 + 3);
+a * 0.5 / 10 / 5.0;
+
+a * 0.5 - 10 - (2.0 + 3);
+a * 0.5 - 10 - 5.0;
+
+x * (10 - 5);
+x * 5;
+
 6 - 2 + 4 * 2 + a;
 12 + a;