You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何构建可处理两种场景的SQL?含成本对象求和与相对值计算

Handling Two Calculation Scenarios in a Single SQL Query

Let’s break this down step by step, starting with clear assumptions about your data structure (adjust as needed for your actual schema). I’ll assume your table is named cost_data with columns: account, entity, cost_object, prd, amount, and is_baseline (a boolean flag for the blue-marked baseline rows).

Scenario 1: Simple Window Function Calculation

As you noted, this is straightforward with window functions. We first calculate the total amount per cost_object, then compute the relative amount (row value divided by the cost object’s total) grouped by prd, cost_object, account, and entity.

SELECT
    prd,
    cost_object,
    account,
    entity,
    amount,
    SUM(amount) OVER (PARTITION BY cost_object) AS total_cost_object_amount,
    -- Add NULLIF to avoid division by zero errors
    amount / NULLIF(SUM(amount) OVER (PARTITION BY cost_object), 0) AS relative_amount
FROM cost_data;

Scenario 2: Complex Association & Summation

Since you mentioned more complex rules, let’s assume the common case where relative amounts are calculated against the baseline row(s) for the same account, entity, and cost_object (tweak the association keys if your actual rule differs).

First, we’ll pre-aggregate baseline values, then join them back to the main table to compute relative amounts:

WITH baseline_totals AS (
    SELECT
        account,
        entity,
        cost_object,
        SUM(amount) AS baseline_amount
    FROM cost_data
    WHERE is_baseline = TRUE
    GROUP BY account, entity, cost_object
)
SELECT
    cd.prd,
    cd.cost_object,
    cd.account,
    cd.entity,
    cd.amount,
    bt.baseline_amount,
    -- Handle division by zero
    cd.amount / NULLIF(bt.baseline_amount, 0) AS relative_amount
FROM cost_data cd
JOIN baseline_totals bt
    ON cd.account = bt.account
    AND cd.entity = bt.entity
    AND cd.cost_object = bt.cost_object;

Combining Both Scenarios into One Flexible Query

To handle both cases in a single SQL, use a parameter (database-specific) or a conditional switch to toggle between logic. Here’s an example using a session parameter:

-- Set your target scenario (1 = window function, 2 = baseline comparison)
SET @scenario = 1;

WITH baseline_totals AS (
    SELECT
        account,
        entity,
        cost_object,
        SUM(amount) AS baseline_amount
    FROM cost_data
    WHERE is_baseline = TRUE
    GROUP BY account, entity, cost_object
)
SELECT
    prd,
    cost_object,
    account,
    entity,
    amount,
    -- Switch comparison total based on scenario
    CASE @scenario
        WHEN 1 THEN SUM(amount) OVER (PARTITION BY cost_object)
        WHEN 2 THEN bt.baseline_amount
    END AS comparison_total,
    -- Calculate relative amount with error handling
    CASE @scenario
        WHEN 1 THEN amount / NULLIF(SUM(amount) OVER (PARTITION BY cost_object), 0)
        WHEN 2 THEN amount / NULLIF(bt.baseline_amount, 0)
    END AS relative_amount
FROM cost_data cd
-- Left join to avoid breaking Scenario 1 if no baseline exists
LEFT JOIN baseline_totals bt
    ON cd.account = bt.account
    AND cd.entity = bt.entity
    AND cd.cost_object = bt.cost_object;

Quick Adjustments for Your Use Case:

  • If Scenario 2 uses different association rules (e.g., matching on prd instead of account), update the JOIN conditions in the CTE.
  • For databases that don’t support session variables (like PostgreSQL), replace @scenario with a query parameter or hardcode the scenario value for testing.

内容的提问来源于stack exchange,提问作者Antti Ruokanen

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:54:01