Bob124 opened a new issue, #45964:
URL: https://github.com/apache/superset/issues/45964

   ### Bug description
   
   ### Bug description
   
   When a Table chart has **two or more temporal (date) dimensions**, the "Time 
grain" setting is applied to only the first temporal column. The remaining 
temporal columns are sent to the database as raw columns, so rows that differ 
only by day/time no longer collapse into one row. This is a regression: the 
same chart works correctly on 4.0.2.
   
   Example: with Dimensions `StartDate`, `EndDate` and Time grain `Month`, the 
chart returns three rows that all display as "Aug 2026 / Sep 2026" but have 
different counts (4, 1, 1), because `EndDate` is not grouped by month.
   
   ### Steps to reproduce
   
   1. Use a dataset (or physical table) that has two temporal columns, e.g. 
`StartDate` and `EndDate`.
   2. Create a **Table** chart (`table_v2`).
   3. Set Query mode = Aggregate.
   4. Dimensions: `StartDate`, `EndDate`.
   5. Metric: `COUNT(DISTINCT Counts)` (any aggregate metric).
   6. Set **Time grain** = `Month`.
   7. Click "Update chart" and inspect the generated SQL ("View query").
   
   Minimal form data:
   
   ```json
   {
     "viz_type": "table",
     "query_mode": "aggregate",
     "granularity_sqla": "StartDate",
     "time_grain_sqla": "P1M",
     "columns": ["StartDate", "EndDate"],
     "metrics": ["COUNT_DISTINCT(Counts)"],
     "temporal_columns_lookup": { "StartDate": true, "EndDate": true }
   }
   ```
   
   ### Expected behavior
   
   Time grain should be applied to **every** temporal column that is used as a 
dimension (the 4.0.2 behavior), i.e. both `StartDate` and `EndDate` should be 
truncated to month and grouped. Expected SQL:
   
   ```sql
   SELECT
     TO_DATE(DATE_SUB(`StartDate`, INTERVAL (DAYOFMONTH(`StartDate`) - 1) DAY)) 
AS `StartDate`,
     TO_DATE(DATE_SUB(`EndDate`,   INTERVAL (DAYOFMONTH(`EndDate`)   - 1) DAY)) 
AS `EndDate`,
     COUNT(DISTINCT `Counts`) AS `Counts`
   FROM `activity`
   WHERE ...
   GROUP BY
     TO_DATE(DATE_SUB(`StartDate`, INTERVAL (DAYOFMONTH(`StartDate`) - 1) DAY)),
     TO_DATE(DATE_SUB(`EndDate`,   INTERVAL (DAYOFMONTH(`EndDate`)   - 1) DAY))
   ```
   
   Result: one row — `Aug 2026 | Sep 2026 | 6`.
   
   ### Actual behavior
   
   Only the first temporal column is converted to a time-grain expression; the 
second one is passed through unchanged:
   
   ```sql
   SELECT
     TO_DATE(DATE_SUB(`StartDate`, INTERVAL (DAYOFMONTH(`StartDate`) - 1) DAY)) 
AS `StartDate`,
     `EndDate` AS `EndDate`,
     COUNT(DISTINCT `Counts`) AS `Counts`
   FROM `activity`
   WHERE
     `StartDate` >= STR_TO_DATE('2026-08-01', '%Y-%m-%d')
     AND `StartDate` < STR_TO_DATE('2026-08-31', '%Y-%m-%d')
     AND `EndDate` >= STR_TO_DATE('2026-09-01', '%Y-%m-%d')
     AND `EndDate` < STR_TO_DATE('2026-09-30', '%Y-%m-%d')
   GROUP BY
     TO_DATE(DATE_SUB(`StartDate`, INTERVAL (DAYOFMONTH(`StartDate`) - 1) DAY)),
     `EndDate`
   ORDER BY `Counts` DESC
   LIMIT 10000
   ```
   
   Result (duplicated dimension combinations, all displayed as the same month):
   
   | StartDate | EndDate | Counts |
   |---|---|---|
   | Aug 2026 | Sep 2026 | 4 |
   | Aug 2026 | Sep 2026 | 1 |
   | Aug 2026 | Sep 2026 | 1 |
   
   Because the raw `EndDate` values differ (different days) while the column is 
rendered as "Sep 2026", the rows look identical to the user but are not 
aggregated — the numbers silently look wrong.
   
   ### Root cause
   
   `superset-frontend/plugins/plugin-chart-table/src/buildQuery.ts`
   
   4.0.2 maps over all columns and replaces **each** temporal column with an 
ad-hoc time-grain column (position preserved):
   
   ```ts
   columns = columns.map(col => {
     if (
       isPhysicalColumn(col) &&
       time_grain_sqla &&
       formData?.temporal_columns_lookup?.[col]
     ) {
       return {
         timeGrain: time_grain_sqla,
         columnType: 'BASE_AXIS',
         sqlExpression: col,
         label: col,
         expressionType: 'SQL',
       } as AdhocColumn;
     }
     return col;
   });
   ```
   
   6.1.0 uses a `temporalColumnAdded` flag, so only the first matching column 
is converted; all subsequent temporal columns fall through unchanged. It also 
removes that column and re-adds it at index 0:
   
   ```ts
   let temporalColumnAdded = false;
   let temporalColumn = null;
   
   columns = columns.filter(col => {
     const shouldBeAdded =
       isPhysicalColumn(col) &&
       time_grain_sqla &&
       temporalColumnsLookup?.[col];
   
     if (shouldBeAdded && !temporalColumnAdded) {
       temporalColumn = {
         timeGrain: time_grain_sqla,
         columnType: 'BASE_AXIS',
         sqlExpression: col,
         label: col,
         expressionType: 'SQL',
       } as AdhocColumn;
       temporalColumnAdded = true;
       return false;
     }
     return true;
   });
   
   if (temporalColumn) {
     columns = [temporalColumn, ...columns];
   }
   ```
   
   The same logic exists in 
`plugins/plugin-chart-ag-grid-table/src/buildQuery.ts` (experimental AG Grid 
Table), so that chart is affected too. Pivot Table does not contain this code 
path.
   
   ### Suggested fix
   
   Keep the "temporal column first" presentation behavior if it is intentional, 
but do not use a single `temporalColumnAdded` flag to decide whether to apply 
the grain — apply the grain to every physical temporal column, e.g.:
   
   ```ts
   columns = columns.map(col =>
     isPhysicalColumn(col) && time_grain_sqla && temporalColumnsLookup?.[col]
       ? {
           timeGrain: time_grain_sqla,
           columnType: 'BASE_AXIS',
           sqlExpression: col,
           label: col,
           expressionType: 'SQL',
         }
       : col,
   );
   ```
   
   and reorder afterwards only if the "first temporal column first" behavior is 
still desired.
   
   ### Workaround
   
   - Use only one temporal dimension per chart, or
   - Wrap the second date dimension as an ad-hoc "Custom SQL" column that 
truncates explicitly, e.g. `DATE_FORMAT(\`EndDate\`, '%Y-%m-01')` 
(database-specific), or
   - Pre-truncate the date in the dataset / SQL before charting.
   
   Note: swapping the order of the two dimensions only moves the problem to the 
other column.
   
   ### Screenshots/recordings
   
   _No response_
   
   ### Superset version
   
   6.1.0
   
   ### Python version
   
   3.11
   
   ### Node version
   
   16
   
   ### Browser
   
   Chrome
   
   ### Additional context
   
   _No response_
   
   ### Checklist
   
   - [x] I have searched Superset docs and Slack and didn't find a solution to 
my problem.
   - [x] I have searched the GitHub issue tracker and didn't find a similar bug 
report.
   - [x] I have checked Superset's logs for errors and if I found a relevant 
Python stacktrace, I included it here as text in the "additional context" 
section.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


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

  • [I] [Bug] Table chart a... Bob124 (via GitHub) via notifications

Reply via email to