Repository: apache/superset
Pull request #33407: fix(big number with trendline): add None option to the aggregation method dropdown
Author: login: LevisNgigi
Labels: name: size/L
name: viz:charts:bignumber
description: Related to BigNumber charts
name: plugins
name: packages
name: 🏷️ bot
description: A label used by `supersetbot` to keep track of which PR where auto-tagged with release labels
name: 🚢 6.0.0
description: First shipped in 6.0.0
Created: 2025-05-12T09:14:39Z | Merged: 2025-05-29T12:33:04Z

### SUMMARY
This PR improves the Big Number with Trendline chart by adding the "None" aggregation method in the dropdown. Previously, aggregation was applied, even for non-additive metrics such as COUNT(DISTINCT ...) or ratio expressions, resulting in misleading or incorrect Big Numbers.

Now, when None is selected in the dropdown, the Big Number query omits time-based grouping and computes the raw metric over the entire date range similar to the Big Number without trendline.

This allows correct visualization of non-additive metrics while retaining support for additive ones via the optional dropdown.

### BEFORE/AFTER SCREENSHOTS OR ANIMATED GIF

https://github.com/user-attachments/assets/7db0f1fb-cbf0-4d92-83ae-0445872f4019


### TESTING INSTRUCTIONS
1. Go to Explore and select the "Big Number with Trendline" chart.
2. Choose a non-additive metric (e.g. `COUNT(*) / COUNT(DISTINCT gender)`).
3. Set a time grain (e.g. monthly).
4. Choose "None" in the dropdown for aggregation method
5. Click "Run".
6. Verify that the Big Number displays a single raw value across the entire date range, and the trendline shows the correct per-period values.

Also verify:
- Additive metrics (e.g. SUM) work as before.


### ADDITIONAL INFORMATION
<!--- Check any relevant boxes with "x" -->
<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->
- [ ] Has associated issue:
- [ ] Required feature flags:
- [ ] Changes UI
- [ ] Includes DB Migration (follow approval process in [SIP-59](https://github.com/apache/superset/issues/13351))
  - [ ] Migration is atomic, supports rollback & is backwards-compatible
  - [ ] Confirm DB migration upgrade and downgrade tested
  - [ ] Runtime estimates and downtime expectations provided
- [ ] Introduces new feature or API
- [ ] Removes existing feature or API



Diff:
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/operators/aggregateOperator.ts b/superset-frontend/packages/superset-ui-chart-controls/src/operators/aggregateOperator.ts
index aa3c518ad926..1431fbac2c6d 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/operators/aggregateOperator.ts
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/operators/aggregateOperator.ts
@@ -30,7 +30,7 @@ export const aggregationOperator: PostProcessingFactory<
 > = (formData: QueryFormData, queryObject) => {
   const { aggregation = 'LAST_VALUE' } = formData;
 
-  if (aggregation === 'LAST_VALUE') {
+  if (aggregation === 'LAST_VALUE' || aggregation === 'raw') {
     return undefined;
   }
 
diff --git a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/customControls.tsx b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/customControls.tsx
index 971e2b39fc57..0f626c92390b 100644
--- a/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/customControls.tsx
+++ b/superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/customControls.tsx
@@ -70,6 +70,7 @@ export const aggregationControl = {
     clearable: false,
     renderTrigger: false,
     choices: [
+      ['raw', t('None')],
       ['LAST_VALUE', t('Last Value')],
       ['sum', t('Total (Sum)')],
       ['mean', t('Average (Mean)')],
@@ -77,7 +78,9 @@ export const aggregationControl = {
       ['max', t('Maximum')],
       ['median', t('Median')],
     ],
-    description: t('Select an aggregation method to apply to the metric.'),
+    description: t(
+      'Aggregation method used to compute the Big Number from the Trendline.For non-additive metrics like ratios, averages, distinct counts, etc use NONE.',
+    ),
     provideFormDataToProps: true,
     mapStateToProps: ({ form_data }: ControlPanelState) => ({
       value: form_data.aggregation || 'LAST_VALUE',
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.test.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.test.ts
new file mode 100644
index 000000000000..e69d32646ddf
--- /dev/null
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.test.ts
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import { QueryFormData } from '@superset-ui/core';
+import buildQuery from './buildQuery';
+
+jest.mock('@superset-ui/core', () => ({
+  ...jest.requireActual('@superset-ui/core'),
+  getXAxisColumn: jest.fn(() => 'order_date'),
+  isXAxisSet: jest.fn(() => true),
+}));
+
+jest.mock('@superset-ui/chart-controls', () => ({
+  pivotOperator: jest.fn(() => ({ operation: 'pivot' })),
+  aggregationOperator: jest.fn(formData => {
+    if (formData.aggregation === 'LAST_VALUE' || !formData.aggregation) {
+      return undefined;
+    }
+    return {
+      operation: 'aggregation',
+      options: { operator: formData.aggregation },
+    };
+  }),
+  flattenOperator: jest.fn(() => ({ operation: 'flatten' })),
+  resampleOperator: jest.fn(() => ({ operation: 'resample' })),
+  rollingWindowOperator: jest.fn(() => ({ operation: 'rolling' })),
+}));
+
+describe('BigNumberWithTrendline buildQuery', () => {
+  const baseFormData: QueryFormData = {
+    datasource: '1__table',
+    viz_type: 'big_number',
+    metric: 'custom_metric',
+    aggregation: null,
+  };
+
+  it('creates raw metric query when aggregation is null', () => {
+    const queryContext = buildQuery({ ...baseFormData });
+    const bigNumberQuery = queryContext.queries[1];
+
+    expect(bigNumberQuery.post_processing).toEqual([{ operation: 'pivot' }]);
+    expect(bigNumberQuery.is_timeseries).toBe(true);
+  });
+
+  it('adds aggregation operator when aggregation is "sum"', () => {
+    const queryContext = buildQuery({ ...baseFormData, aggregation: 'sum' });
+    const bigNumberQuery = queryContext.queries[1];
+
+    expect(bigNumberQuery.post_processing).toEqual([
+      { operation: 'pivot' },
+      { operation: 'aggregation', options: { operator: 'sum' } },
+    ]);
+    expect(bigNumberQuery.is_timeseries).toBe(true);
+  });
+
+  it('skips aggregation when aggregation is LAST_VALUE', () => {
+    const queryContext = buildQuery({
+      ...baseFormData,
+      aggregation: 'LAST_VALUE',
+    });
+    const bigNumberQuery = queryContext.queries[1];
+
+    expect(bigNumberQuery.post_processing).toEqual([{ operation: 'pivot' }]);
+    expect(bigNumberQuery.is_timeseries).toBe(true);
+  });
+
+  it('always returns two queries', () => {
+    const queryContext = buildQuery({ ...baseFormData });
+    expect(queryContext.queries.length).toBe(2);
+  });
+});
diff --git a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.ts b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.ts
index 398125719b1e..5fb46aa96c5c 100644
--- a/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.ts
+++ b/superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.ts
@@ -16,6 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
+
 import {
   buildQueryContext,
   ensureIsArray,
@@ -32,15 +33,17 @@ import {
 } from '@superset-ui/chart-controls';
 
 export default function buildQuery(formData: QueryFormData) {
+  const isRawMetric = formData.aggregation === 'raw';
+
+  const timeColumn = isXAxisSet(formData)
+    ? ensureIsArray(getXAxisColumn(formData))
+    : [];
+
   return buildQueryContext(formData, baseQueryObject => [
     {
       ...baseQueryObject,
-      columns: [
-        ...(isXAxisSet(formData)
-          ? ensureIsArray(getXAxisColumn(formData))
-          : []),
-      ],
-      ...(isXAxisSet(formData) ? {} : { is_timeseries: true }),
+      columns: [...timeColumn],
+      ...(timeColumn.length ? {} : { is_timeseries: true }),
       post_processing: [
         pivotOperator(formData, baseQueryObject),
         rollingWindowOperator(formData, baseQueryObject),
@@ -48,19 +51,16 @@ export default function buildQuery(formData: QueryFormData) {
         flattenOperator(formData, baseQueryObject),
       ],
     },
-
     {
       ...baseQueryObject,
-      columns: [
-        ...(isXAxisSet(formData)
-          ? ensureIsArray(getXAxisColumn(formData))
-          : []),
-      ],
-      ...(isXAxisSet(formData) ? {} : { is_timeseries: true }),
-      post_processing: [
-        pivotOperator(formData, baseQueryObject),
-        aggregationOperator(formData, baseQueryObject),
-      ],
+      columns: [...(isRawMetric ? [] : timeColumn)],
+      is_timeseries: !isRawMetric,
+      post_processing: isRawMetric
+        ? []
+        : [
+            pivotOperator(formData, baseQueryObject),
+            aggregationOperator(formData, baseQueryObject),
+          ],
     },
   ]);
 }


Reviews:
user: login: korbit-ai[bot]
body: ### Review by Korbit AI

###### Korbit automatically attempts to detect when you fix issues in new commits.

| Category | Issue | Status |
|----------|-------|----------|
| <sub>![Functionality](https://img.shields.io/badge/Functionality-0284c7)</sub> | Incorrect Time Series Flag Logic ▹ [view]( https://github.com/apache/superset/pull/33407#discussion_r2084224233 ) | ✅ Fix detected |
| <sub>![Functionality](https://img.shields.io/badge/Functionality-0284c7)</sub> | Missing Essential Post-Processing ▹ [view]( https://github.com/apache/superset/pull/33407#discussion_r2084224239 ) | ✅ Fix detected |






<details>
  <summary>Files scanned</summary>
&#8203;



| File Path | Reviewed |
| ------------------ | -------------- |
| superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.ts | ✅ |
| superset-frontend/packages/superset-ui-chart-controls/src/shared-controls/customControls.tsx | ✅ |


> Explore our [documentation](https://docs.korbit.ai) to understand the languages and file types [we support](https://docs.korbit.ai/configuration/supported-languages) and the [files we ignore](https://docs.korbit.ai/configuration/ignoring-files).

</details>





> Check out our [docs](https://docs.korbit.ai) on how you can make Korbit work best for you and your team.
>
> Loving Korbit!? Share us on [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https://www.korbit.ai&text=Korbit%20AI-powered%20Code%20Reviews%20are%20awesome...) [Reddit](https://www.reddit.com/submit?url=https://www.korbit.ai&title=Korbit%20AI-powered%20Code%20Reviews%20are%20awesome...) and [X](https://x.com/intent/tweet?text=Korbit%20AI-powered%20Code%20Reviews%20are%20awesome...%0A%0Ahttps%3A%2F%2Fwww.korbit.ai%0A%0A@KorbitAi)


state: COMMENTED
author_association: NONE
submitted_at: 2025-05-12T09:17:39Z
user: login: LevisNgigi
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-05-12T11:02:15Z
user: login: korbit-ai[bot]
state: COMMENTED
author_association: NONE
submitted_at: 2025-05-12T11:02:41Z
user: login: geido
state: APPROVED
author_association: MEMBER
submitted_at: 2025-05-29T12:32:53Z

Review comments:
diff_hunk: @@ -52,15 +52,19 @@ export default function buildQuery(formData: QueryFormData) {
     {
       ...baseQueryObject,
       columns: [
-        ...(isXAxisSet(formData)
-          ? ensureIsArray(getXAxisColumn(formData))
+        ...(formData.aggregation
+          ? isXAxisSet(formData)
+            ? ensureIsArray(getXAxisColumn(formData))
+            : []
           : []),
       ],
-      ...(isXAxisSet(formData) ? {} : { is_timeseries: true }),
-      post_processing: [
-        pivotOperator(formData, baseQueryObject),
-        aggregationOperator(formData, baseQueryObject),
-      ],
+      is_timeseries: !!formData.aggregation,
path: superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.ts
user: login: korbit-ai[bot]
body: ### Incorrect Time Series Flag Logic <sub>![category Functionality](https://img.shields.io/badge/Functionality-0284c7)</sub>

<details>
  <summary>Tell me more</summary>

###### What is the issue?
The is_timeseries flag is incorrectly tied to the presence of aggregation, when it should be based on whether an X-axis is set (as in the first query object).

###### Why this matters
This could cause incorrect data processing for time series data when no aggregation is selected, potentially leading to visualization errors or data misrepresentation.

###### Suggested change ∙ *Feature Preview*
The is_timeseries flag should maintain the same logic as the first query object:
```typescript
      ...(isXAxisSet(formData) ? {} : { is_timeseries: true }),
```


###### Provide feedback to improve future suggestions
[![Nice Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/526a4bc5-4e0c-409a-8916-83a32dae1c19/upvote) [![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/526a4bc5-4e0c-409a-8916-83a32dae1c19?what_not_true=true)  [![Not in Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/526a4bc5-4e0c-409a-8916-83a32dae1c19?what_out_of_scope=true) [![Not in coding standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/526a4bc5-4e0c-409a-8916-83a32dae1c19?what_not_in_standard=true) [![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/526a4bc5-4e0c-409a-8916-83a32dae1c19)
</details>

<sub>

💬 Looking for more details? Reply to this comment to chat with Korbit.
</sub>

<!--- korbi internal id:75dc8d09-d748-4e67-bf96-cce6394a188d -->


[](75dc8d09-d748-4e67-bf96-cce6394a188d)
created_at: 2025-05-12T09:17:39Z
author_association: NONE
diff_hunk: @@ -52,15 +52,19 @@
     {
       ...baseQueryObject,
       columns: [
-        ...(isXAxisSet(formData)
-          ? ensureIsArray(getXAxisColumn(formData))
+        ...(formData.aggregation
+          ? isXAxisSet(formData)
+            ? ensureIsArray(getXAxisColumn(formData))
+            : []
           : []),
       ],
-      ...(isXAxisSet(formData) ? {} : { is_timeseries: true }),
-      post_processing: [
-        pivotOperator(formData, baseQueryObject),
-        aggregationOperator(formData, baseQueryObject),
-      ],
+      is_timeseries: !!formData.aggregation,
+      post_processing: formData.aggregation
+        ? [
+            pivotOperator(formData, baseQueryObject),
+            aggregationOperator(formData, baseQueryObject),
+          ]
+        : [],
path: superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.ts
user: login: korbit-ai[bot]
body: ### Missing Essential Post-Processing <sub>![category Functionality](https://img.shields.io/badge/Functionality-0284c7)</sub>

<details>
  <summary>Tell me more</summary>

###### What is the issue?
When aggregation is disabled, all post-processing operations are skipped, including pivoting which might still be necessary for proper data transformation.

###### Why this matters
This could result in incorrectly structured data when pivoting is required but aggregation is not selected, leading to visualization failures.

###### Suggested change ∙ *Feature Preview*
Separate the pivot operation from the aggregation condition:
```typescript
      post_processing: [
        pivotOperator(formData, baseQueryObject),
        ...(formData.aggregation ? [aggregationOperator(formData, baseQueryObject)] : []),
      ],
```


###### Provide feedback to improve future suggestions
[![Nice Catch](https://img.shields.io/badge/👍%20Nice%20Catch-71BC78)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/6f1fe1b8-933f-4b7d-aad1-60a025293765/upvote) [![Incorrect](https://img.shields.io/badge/👎%20Incorrect-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/6f1fe1b8-933f-4b7d-aad1-60a025293765?what_not_true=true)  [![Not in Scope](https://img.shields.io/badge/👎%20Out%20of%20PR%20scope-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/6f1fe1b8-933f-4b7d-aad1-60a025293765?what_out_of_scope=true) [![Not in coding standard](https://img.shields.io/badge/👎%20Not%20in%20our%20standards-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/6f1fe1b8-933f-4b7d-aad1-60a025293765?what_not_in_standard=true) [![Other](https://img.shields.io/badge/👎%20Other-white)](https://app.korbit.ai/feedback/aa91ff46-6083-4491-9416-b83dd1994b51/6f1fe1b8-933f-4b7d-aad1-60a025293765)
</details>

<sub>

💬 Looking for more details? Reply to this comment to chat with Korbit.
</sub>

<!--- korbi internal id:94b9b312-ed06-4d0d-9c84-4ddc8b957ff8 -->


[](94b9b312-ed06-4d0d-9c84-4ddc8b957ff8)
created_at: 2025-05-12T09:17:39Z
author_association: NONE
diff_hunk: @@ -52,15 +52,19 @@
     {
       ...baseQueryObject,
       columns: [
-        ...(isXAxisSet(formData)
-          ? ensureIsArray(getXAxisColumn(formData))
+        ...(formData.aggregation
+          ? isXAxisSet(formData)
+            ? ensureIsArray(getXAxisColumn(formData))
+            : []
           : []),
       ],
-      ...(isXAxisSet(formData) ? {} : { is_timeseries: true }),
-      post_processing: [
-        pivotOperator(formData, baseQueryObject),
-        aggregationOperator(formData, baseQueryObject),
-      ],
+      is_timeseries: !!formData.aggregation,
+      post_processing: formData.aggregation
+        ? [
+            pivotOperator(formData, baseQueryObject),
+            aggregationOperator(formData, baseQueryObject),
+          ]
+        : [],
path: superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.ts
user: login: LevisNgigi
body: Thanks! I tried separating pivotOperator, but without aggregation, the time column is removed, which causes pivot to fail. So I kept it conditional to avoid data errors when the time column isn’t present. Also, not all post-processing is skipped, only the aggregation step is skipped when no aggregation method is selected.
created_at: 2025-05-12T11:02:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -52,15 +52,19 @@
     {
       ...baseQueryObject,
       columns: [
-        ...(isXAxisSet(formData)
-          ? ensureIsArray(getXAxisColumn(formData))
+        ...(formData.aggregation
+          ? isXAxisSet(formData)
+            ? ensureIsArray(getXAxisColumn(formData))
+            : []
           : []),
       ],
-      ...(isXAxisSet(formData) ? {} : { is_timeseries: true }),
-      post_processing: [
-        pivotOperator(formData, baseQueryObject),
-        aggregationOperator(formData, baseQueryObject),
-      ],
+      is_timeseries: !!formData.aggregation,
+      post_processing: formData.aggregation
+        ? [
+            pivotOperator(formData, baseQueryObject),
+            aggregationOperator(formData, baseQueryObject),
+          ]
+        : [],
path: superset-frontend/plugins/plugin-chart-echarts/src/BigNumber/BigNumberWithTrendline/buildQuery.ts
user: login: korbit-ai[bot]
body: That makes sense - I understand now that pivot requires the time column which is only present with aggregation. Thanks for explaining the technical constraint.
created_at: 2025-05-12T11:02:41Z
author_association: NONE

PR comments:
user: login: github-actions[bot]
created_at: 2025-05-14T15:24:27Z
body: @geido Processing your ephemeral environment request [here](https://github.com/apache/superset/actions/runs/15024700038). Action: **up**. More information on [how to use or configure ephemeral environments](https://superset.apache.org/docs/contributing/howtos/#github-ephemeral-environments)
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-14T15:33:14Z
body: @geido Ephemeral environment spinning up at http://54.149.153.58:8080. Credentials are 'admin'/'admin'. Please allow several minutes for bootstrapping and startup.
author_association: CONTRIBUTOR
user: login: rusackas
created_at: 2025-05-14T17:38:11Z
body: Pinging @mistercrunch since he's always been a part of the "to aggregate or not to aggregate" threads :) 
author_association: MEMBER
user: login: rusackas
created_at: 2025-05-14T17:38:59Z
body: How does the trendline work now? Can you add some screenshots/test data?
author_association: MEMBER
user: login: LevisNgigi
created_at: 2025-05-14T18:32:08Z
body: > How does the trendline work now? Can you add some screenshots/test data?

@rusackas trendline is not affected,this just affects the value of the Big Number, will definitely add a video,after finalizing a nit.
author_association: CONTRIBUTOR
user: login: mistercrunch
created_at: 2025-05-15T17:37:18Z
body: Isn't this the same as `LAST_VALUE`? Trying to understand how it differs from it...
author_association: MEMBER
user: login: LevisNgigi
created_at: 2025-05-16T09:03:36Z
body: > Isn't this the same as `LAST_VALUE`? Trying to understand how it differs from it...

@mistercrunch LAST_VALUE returns the final value from a sorted result set. That’s fine, but for this we need the big number to display the raw metric value for non-additive metrics like  ratios, or percentages.

In this case, we're not just interested in the last data point — we're trying to reflect the raw metric over the entire time range, as it exists in the source data.
author_association: CONTRIBUTOR
user: login: mistercrunch
created_at: 2025-05-16T15:57:27Z
body: Oh so say for a `COUNT(DISTINCT user_id)`,  if the length of the trendline is 30 days, it would show `DAU` on the trendline for overall count distinct over the period for the big number (MAU)? Doesn't that require running two queries? Wondering if/how that works on this PR as is (?)
author_association: MEMBER
user: login: LevisNgigi
created_at: 2025-05-16T21:01:40Z
body: > Oh so say for a `COUNT(DISTINCT user_id)`, if the length of the trendline is 30 days, it would show `DAU` on the trendline for overall count distinct over the period for the big number (MAU)? Doesn't that require running two queries? Wondering if/how that works on this PR as is (?)

As per my investigation and modification so far this PR follows that structure, so the trendline shows granular values (e.g., daily counts), and the big number reflects an aggregate (or raw) value across the selected period. It works as expected for non-additive metrics like COUNT(DISTINCT user_id) when no aggregation method is selected.
author_association: CONTRIBUTOR
user: login: mistercrunch
created_at: 2025-05-16T22:01:03Z
body: Oh so there are some mechanics behind there that will run 2 queries? I know we do that in some special cases like maybe "show totals" in the Table visualization (?)

Now wondering if we should use this new option as the default of keep LAST_VALUE there (?) Seems generally users would expect LAST_VALUE, but I might not be the right person to decide since I probably built it the way it is today as it seems more intuitive to me...
author_association: MEMBER
user: login: LevisNgigi
created_at: 2025-05-16T23:20:14Z
body: > Oh so there are some mechanics behind there that will run 2 queries? I know we do that in some special cases like maybe "show totals" in the Table visualization (?)
> 
> Now wondering if we should use this new option as the default of keep LAST_VALUE there (?) Seems generally users would expect LAST_VALUE, but I might not be the right person to decide since I probably built it the way it is today as it seems more intuitive to me...

Yes,this setup runs two queries: one for the trendline and another for the big number when no aggregation method is selected. With the new change making aggregation optional, we can't assign a different default like LAST_VALUE, since doing so would prevent users from clearing the selection and reverting to the raw metric. Leaving the control empty is now the explicit signal to compute the raw value across the entire time range.Yes,Last value was previously the default, is the new option is okay ?
author_association: CONTRIBUTOR
user: login: mistercrunch
created_at: 2025-05-17T20:43:12Z
body: > we can't assign a different default like LAST_VALUE

is that right? seems it's totally doable to set anything as a default for the control, and use are able to clear the dropdown if they want. You'd have to pass `clearable` or whatever it's called to the component.

Alternatively you could also introduce a new aggregation type for this new option you are creating. Not sure what exactly to call it, but giving it a clear name would make the new option and behavior more discoverable. 

I'm worried that changing the default to a new behavior is going to confuse users who are used to the current behavior (last_value).
author_association: MEMBER
user: login: LevisNgigi
created_at: 2025-05-19T11:08:25Z
body: > > we can't assign a different default like LAST_VALUE
> 
> is that right? seems it's totally doable to set anything as a default for the control, and use are able to clear the dropdown if they want. You'd have to pass `clearable` or whatever it's called to the component.
> 
> Alternatively you could also introduce a new aggregation type for this new option you are creating. Not sure what exactly to call it, but giving it a clear name would make the new option and behavior more discoverable.
> 
> I'm worried that changing the default to a new behavior is going to confuse users who are used to the current behavior (last_value).

Yes, I’ve been trying to set LAST_VALUE as the default while keeping the dropdown clearable, but there are still some odd behaviors when loading or saving charts with that setup,so I’m continuing to look into it.

I had actually introduced a "Raw Metric" option in the dropdown earlier, but was advised against it since it’s technically not an aggregation method. Including it there could be misleading, as selecting it means we skip aggregation entirely.But it worked well with the default value.

That said, I agree that discoverability is important, and the trade-off between clarity and correctness here is still something we’re balancing,especially since changing the default behavior from LAST_VALUE could be confusing to existing users.
author_association: CONTRIBUTOR
user: login: mistercrunch
created_at: 2025-05-19T22:46:38Z
body: Right. I'm not sure who else advised what before - and sorry for the confusion as we figure things out as we go and often navigate intricate tradeoffs. Maybe we tag whoever had a different view so we can hash it out here.
author_association: MEMBER
user: login: LevisNgigi
created_at: 2025-05-20T06:31:25Z
body: > Right. I'm not sure who else advised what before - and sorry for the confusion as we figure things out as we go and often navigate intricate tradeoffs. Maybe we tag whoever had a different view so we can hash it out here.

No problem,I appreciate that we are navigating some intricate tradeoffs and I am happy with the discussion so far.Just to clarify, @betodealmeida had looked into the current behavior in depth and provided guidance on the most reliable and aligned way forward, based on that investigation. 
author_association: CONTRIBUTOR
user: login: codecov[bot]
created_at: 2025-05-21T09:20:08Z
body: ## [Codecov](https://app.codecov.io/gh/apache/superset/pull/33407?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) Report
:white_check_mark: All modified and coverable lines are covered by tests.
:white_check_mark: Project coverage is 83.17%. Comparing base ([`76d897e`](https://app.codecov.io/gh/apache/superset/commit/76d897eaa2f9e137102bc194c2e3109c29d0348f?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)) to head ([`ed5078f`](https://app.codecov.io/gh/apache/superset/commit/ed5078fa86fc713a11544e463973d4fe22dabc1c?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache)).
:warning: Report is 3194 commits behind head on master.

<details><summary>Additional details and impacted files</summary>



```diff
@@             Coverage Diff             @@
##           master   #33407       +/-   ##
===========================================
+ Coverage   60.48%   83.17%   +22.68%     
===========================================
  Files        1931      553     -1378     
  Lines       76236    39998    -36238     
  Branches     8568        0     -8568     
===========================================
- Hits        46114    33269    -12845     
+ Misses      28017     6729    -21288     
+ Partials     2105        0     -2105     
```

| [Flag](https://app.codecov.io/gh/apache/superset/pull/33407/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | Coverage Δ | |
|---|---|---|
| [javascript](https://app.codecov.io/gh/apache/superset/pull/33407/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache) | `?` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache#carryforward-flags-in-the-pull-request-comment) to find out more.
</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/apache/superset/pull/33407?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=apache).
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
- :package: [JS Bundle Analysis](https://docs.codecov.com/docs/javascript-bundle-analysis): Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
</details>
author_association: NONE
user: login: github-actions[bot]
created_at: 2025-05-21T23:46:50Z
body: @sadpandajoe Processing your ephemeral environment request [here](https://github.com/apache/superset/actions/runs/15174788733). Action: **up**. More information on [how to use or configure ephemeral environments](https://superset.apache.org/docs/contributing/howtos/#github-ephemeral-environments)
author_association: CONTRIBUTOR
user: login: github-actions[bot]
created_at: 2025-05-21T23:58:34Z
body: @sadpandajoe Ephemeral environment spinning up at http://54.189.163.207:8080. Credentials are 'admin'/'admin'. Please allow several minutes for bootstrapping and startup.
author_association: CONTRIBUTOR