This is an automated email from the ASF dual-hosted git repository.

elizabeth pushed a commit to branch fix/time-offset-totals-join
in repository https://gitbox.apache.org/repos/asf/superset.git

commit 40f8d873b20157f02a8e921c573301a53bd85b4a
Author: Elizabeth Thompson <[email protected]>
AuthorDate: Tue Jan 13 17:35:36 2026 -0800

    fix(table chart): time comparison totals returning null
    
    When a table chart has `show_totals=true` and `time_offsets` enabled,
    the totals row was showing null for the time comparison column.
    
    This happened because the totals query has `columns=[]` (no dimension
    columns), and `_determine_join_keys` was trying to create a join column
    from the first column (a numeric metric value) instead of using the
    `__temp_join_key__` fallback mechanism.
    
    The fix checks if there are no join keys AND the first column is not
    a datetime, and in that case returns empty join keys which triggers
    the correct fallback join behavior.
    
    🤖 Generated with [Claude Code](https://claude.com/claude-code)
    
    Co-Authored-By: Claude <[email protected]>
---
 superset/models/helpers.py                  | 10 +++++++++
 tests/unit_tests/common/test_time_shifts.py | 33 +++++++++++++++++++++++++++++
 2 files changed, 43 insertions(+)

diff --git a/superset/models/helpers.py b/superset/models/helpers.py
index a4fb9e3fea..da37869bc3 100644
--- a/superset/models/helpers.py
+++ b/superset/models/helpers.py
@@ -1800,6 +1800,16 @@ class ExploreMixin:  # pylint: 
disable=too-many-public-methods
     ) -> tuple[pd.DataFrame, list[str]]:
         """Determine appropriate join keys and modify DataFrames if needed."""
         if time_grain and not is_date_range_offset:
+            # When there are no join keys (e.g., totals query with columns=[]),
+            # check if the first column is a datetime before attempting to use 
it
+            # for join column generation. If it's not a datetime (e.g., only 
metric
+            # columns exist), fall back to empty join keys which will trigger 
the
+            # __temp_join_key__ mechanism in _perform_join.
+            if not join_keys and len(df.columns) > 0:
+                first_col_dtype = df.iloc[:, 0].dtype
+                if not pd.api.types.is_datetime64_any_dtype(first_col_dtype):
+                    return offset_df, []
+
             column_name = OFFSET_JOIN_COLUMN_SUFFIX + offset
 
             # Add offset join columns for relative time offsets
diff --git a/tests/unit_tests/common/test_time_shifts.py 
b/tests/unit_tests/common/test_time_shifts.py
index 08b6478c48..09984a1922 100644
--- a/tests/unit_tests/common/test_time_shifts.py
+++ b/tests/unit_tests/common/test_time_shifts.py
@@ -209,3 +209,36 @@ def test_join_offset_dfs_with_month_granularity():
     )
 
     assert_frame_equal(expected, result)
+
+
+def test_join_offset_dfs_totals_query_no_dimensions():
+    """
+    Test time offset join for totals query with no dimension columns.
+
+    This simulates a table chart totals query where:
+    - columns=[] (no dimensions, only metrics)
+    - time_offsets=["1 month ago"]
+    - The dataframes only contain metric columns (no datetime column)
+
+    The join should use the __temp_join_key__ fallback mechanism
+    to properly join the offset data.
+    """
+    # Main totals query result - only has metric column, no datetime
+    df = DataFrame({"Total Cost": [54211.76]})
+
+    # Offset query result - renamed metric column
+    offset_df = DataFrame({"Total Cost__1 month ago": [48000.50]})
+
+    offset_dfs = {"1 month ago": offset_df}
+    time_grain = "P1D"  # Daily grain from extras
+    join_keys = []  # No dimension columns for totals query
+
+    expected = DataFrame(
+        {"Total Cost": [54211.76], "Total Cost__1 month ago": [48000.50]}
+    )
+
+    result = query_context_processor.join_offset_dfs(
+        df, offset_dfs, time_grain, join_keys
+    )
+
+    assert_frame_equal(expected, result)

Reply via email to