You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@superset.apache.org by el...@apache.org on 2026/01/14 01:35:55 UTC
(superset) 01/01: fix(table chart): time comparison totals returning null
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 <es...@gmail.com>
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 <no...@anthropic.com>
---
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)