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]