Yaoxuan Wu created SPARK-60156:
----------------------------------

             Summary: Correlated scalar subquery over a DOUBLE sum returns NULL 
for a row that has matches
                 Key: SPARK-60156
                 URL: https://issues.apache.org/jira/browse/SPARK-60156
             Project: Spark
          Issue Type: Bug
          Components: Optimizer
    Affects Versions: 4.1.1, 4.2.0, 3.5.8, 4.0.0, 5.0.0
            Reporter: Yaoxuan Wu


{code:java}
from pyspark.sql import SparkSession
spark = SparkSession.builder.getOrCreate()
spark.createDataFrame([(1, 'a', 1.0), (1, 'b', 1e16), (1, 'a', 1.0), (1, 'b', 
-1e16)],
                      'k int, c string, x double').createOrReplaceTempView('t')
spark.sql("CREATE OR REPLACE TEMP VIEW g AS "
          "SELECT k, count(DISTINCT c) AS n, sum(x) AS s FROM t GROUP BY 
k")spark.table("g").collect()
# [Row(k=1, n=2, s=2.0)]spark.sql("SELECT k, n, s, (SELECT max(x) FROM t WHERE 
t.x < g.s) AS m FROM g").collect()
# expected:    [Row(k=1, n=2, s=2.0, m=1.0)]
# Spark 4.2.0: [Row(k=1, n=2, s=2.0, m=None)]spark.sql("SELECT k, n, s, (SELECT 
count(*) FROM t WHERE t.x < g.s) AS m FROM g").collect()
# expected:    [Row(k=1, n=2, s=2.0, m=3)]
# Spark 4.2.0: [Row(k=1, n=2, s=2.0, m=0)]
{code}
Same on 3.5.8, 4.0.0, 4.1.1, 4.2.0 and master, at default configs.

This is not a question of summation order. The order of a floating-point sum is 
not specified, so s may be 0.0, 1.0 or 2.0. But x = -1e16 is smaller than all 
of them, so under any order {{max}} is not NULL and {{count}} is at least 1. 
Spark returns s = 2.0 for the row, and for 2.0 the answer is 1.0 / 3.

Optimized plan (shortened):
{code:java}
Join LeftOuter, (normalizenanandzero(coalesce(s#121, 0.0)) = 
normalizenanandzero(coalesce(s#129, 0.0)) AND (isnull(s#121) = isnull(s#129)))
:- Aggregate [k#0], [k#0, count(distinct c#1) AS n#120L, sum(x#2) AS s#121]
+- Aggregate [s#129], [max(x#128) AS max(x)#125, s#129]
   +- Join Inner, (x#128 < s#129)
      :- Aggregate [s#121], [s#121 AS s#129]
      :  +- Aggregate [k#0], [sum(x#2) AS s#121]
      +- Project [x#128] ... {code}
Cause: for the non-equality correlation, DecorrelateInnerQuery builds a domain 
join from a second copy of the outer plan and joins the result back on equality 
of s. Column pruning removes count(DISTINCT c) from the copy only. The outer 
side computes sum(x) through the distinct-aggregate rewrite (2.0). The copy 
uses a plain hash aggregate (0.0, the same as SELECT k, sum(x) FROM t GROUP BY 
k). The join back finds no match, so the subquery value is lost.SPARK-55038 has 
the same mechanism with array_agg(DISTINCT) (element order differs between the 
two evaluations). Its proposed fix sorted collect_list/collect_set output, 
which does not help here. Fixing decorrelation would cover both, for example by 
joining back on a row identifier instead of the outer values, or by evaluating 
the outer plan once.scalarSubqueryUseSingleJoin=false, 
decorrelateJoinPredicate.enabled=false and adaptive.enabled=false do not change 
the result. decorrelateInnerQuery.enabled=false rejects the query.



--
This message was sent by Atlassian Jira
(v8.20.10#820010)

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to