作为子查询一部分的 SQL 列的运行总计

发布于 2025-01-19 04:05:55 字数 1760 浏览 6 评论 0原文

这里有很多帖子描述了如何进行运行总计,但是我面对的是,运行总计需要是使用子问题计算的列的列(这意味着我的当前订单会导致查询失败)

我有一个显示每个时间段数量的表格,类似的时间:

TimePeriod   Amount
2022-03-31   396
2022-03-31   16
2022-03-31   84
2021-12-31   842
2021-12-31   57
2021-09-30   652
2021-09-30   25
2021-09-30   173

在我的查询中,我需要找到每个时间段的总数。我所做的是:

SELECT 
    TimePeriod,
    SUM(Amount) AS 'Total Per Period', 
    CAST( ROUND( SUM(Amount)/(SELECT SUM(Amount) FROM MyDatabase.MyTable),3) AS DECIMAL(12,3)) AS 'Percentage of Total'
FROM
    MyDatabase.MyTable
GROUP BY
    TimePeriod
ORDER BY
    TimePeriod DESC

这给了我正确的输出,例如:

TimePeriod   Total per Period   Percentage of total
2022-03-31   496                0.221
2021-12-31   899                0.400
2021-09-30   850                0.379

我想做的就是添加“总列的百分比”的总计,类似:

TimePeriod   Total per Period   Percentage of total   Running total percentage
2022-03-31   496                0.221                 0.221
2021-12-31   899                0.400                 0.621
2021-09-30   850                0.379                 1.000

我尝试做的是首先添加它在第一个选择子句中,但这不起作用,因为它是我查询中仅存在的列。然后,我尝试选择一个选择,这样的选择:

SELECT
    TimePeriod,
    'Total Per Period',
    'Percentage of Total',
    SUM('Percentage of Total') OVER (ORDER BY TimePeriod)
FROM
    (SELECT 
        TimePeriod,
        SUM(Amount) AS 'Total Per Period', 
        CAST( ROUND( SUM(Amount)/(SELECT SUM(Amount) FROM MyDatabase.MyTable),3) AS DECIMAL(12,3)) AS 'Percentage of Total'
    FROM
        MyDatabase.MyTable
    GROUP BY
        TimePeriod
    ORDER BY
        TimePeriod DESC)

这引发了错误,说出最后一个顺序不允许在子征服中。取而代之的是说语法不正确。我猜想问题是我有一个子查询参考子查询结果,但我不确定如何处理这个结果。我的查询似乎缺少什么?

Lots of posts here describe how to do running totals, but I'm faced with a situation where the running total needs to be that of a column that's calculated using a sub-query (which means my current ORDER BY causes the query to fail)

I have a table that show amounts per time period, something like this:

TimePeriod   Amount
2022-03-31   396
2022-03-31   16
2022-03-31   84
2021-12-31   842
2021-12-31   57
2021-09-30   652
2021-09-30   25
2021-09-30   173

In my query, I need to find the percentage of the total for each time period. What I've done is this:

SELECT 
    TimePeriod,
    SUM(Amount) AS 'Total Per Period', 
    CAST( ROUND( SUM(Amount)/(SELECT SUM(Amount) FROM MyDatabase.MyTable),3) AS DECIMAL(12,3)) AS 'Percentage of Total'
FROM
    MyDatabase.MyTable
GROUP BY
    TimePeriod
ORDER BY
    TimePeriod DESC

This gives me a correct output, like so:

TimePeriod   Total per Period   Percentage of total
2022-03-31   496                0.221
2021-12-31   899                0.400
2021-09-30   850                0.379

What I want to do is add a running total of the 'Percentage of total' column, something like:

TimePeriod   Total per Period   Percentage of total   Running total percentage
2022-03-31   496                0.221                 0.221
2021-12-31   899                0.400                 0.621
2021-09-30   850                0.379                 1.000

What I tried to do was first just add it in the first SELECT clause but that doesn't work since it's a column that only exists in my query. I then tried to do a select of that select, like so:

SELECT
    TimePeriod,
    'Total Per Period',
    'Percentage of Total',
    SUM('Percentage of Total') OVER (ORDER BY TimePeriod)
FROM
    (SELECT 
        TimePeriod,
        SUM(Amount) AS 'Total Per Period', 
        CAST( ROUND( SUM(Amount)/(SELECT SUM(Amount) FROM MyDatabase.MyTable),3) AS DECIMAL(12,3)) AS 'Percentage of Total'
    FROM
        MyDatabase.MyTable
    GROUP BY
        TimePeriod
    ORDER BY
        TimePeriod DESC)

This throws the error saying that the last ORDER BY is not allowed in sub-queries. Removing ORDER BY instead says that the syntax is incorrect. I'm guessing that the problem is that I have a subquery referencing a subquery result, but I'm not sure how to work around this one. What seems to be missing from my query?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

杀手六號 2025-01-26 04:05:55

您有一些语法错误,以及要进行的一些改进:

  • 如其他答案中所述,派生表需要一个别名
  • 使用[]在必要时报价列名(最好没有此类首先是列名)。
  • 您不能在派生的表或子查询内通过进行顺序,也不有意义。
  • 您可以将选择Sum子查询( sum(sum))上的()窗口函数。
  • 运行的总窗口函数必须具有行无界的,如果timePeriod可能具有重复。它也更快。
  • 因为您是通过timePeriod desc订购的,所以以与Main 订单相同的顺序进行运行总数可能更快无限之后的可以符合相同的结果。好处是查询计划中的一种。
SELECT
    TimePeriod,
    [Total Per Period],
    [Percentage of Total],
    SUM([Percentage of Total]) OVER (ORDER BY TimePeriod DESC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
FROM
    (SELECT 
        TimePeriod,
        SUM(Amount) AS [Total Per Period],
        CAST( ROUND( SUM(Amount) / SUM(SUM(Amount)) OVER () , 3) AS DECIMAL(12,3)) AS [Percentage of Total]
    FROM
        MyDatabase.MyTable
    GROUP BY
        TimePeriod
) t
ORDER BY
    TimePeriod DESC;

进一步的改进是将整个过程结合在一起:

SELECT
    TimePeriod,
    SUM(Amount) AS [Total Per Period],
    CAST( ROUND(
            SUM(Amount) /
            SUM(SUM(Amount)) OVER ()
          , 3) AS DECIMAL(12,3)) AS [Percentage of Total],
    CAST( ROUND(
            SUM(SUM(Amount)) OVER (ORDER BY TimePeriod DESC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) /
            SUM(SUM(Amount)) OVER ()
          , 3) AS DECIMAL(12,3))
FROM
    MyDatabase.MyTable
GROUP BY
    TimePeriod
ORDER BY
    TimePeriod DESC;

请注意,由于舍入的结果可能会略有不同。

sql小提琴

You have some syntax errors, as well as some improvements to make:

  • As mentioned in the other answer, the derived table needs an alias
  • Use [] to quote column names if necessary (preferably don't have such column names in the first place).
  • You cannot have ORDER BY inside a derived table or subquery, nor does it make sense to do so.
  • You can replace the SELECT SUM subquery with SUM(SUM) OVER () window function.
  • The running total window function must have ROWS UNBOUNDED PRECEDING if TimePeriod may have duplicates. It's also faster.
  • Because you are ordering by TimePeriod DESC, it may be faster to do the running total in the same order as the main ORDER BY but with ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING which works out to the same results. The benefit is one less sort in the query plan.
SELECT
    TimePeriod,
    [Total Per Period],
    [Percentage of Total],
    SUM([Percentage of Total]) OVER (ORDER BY TimePeriod DESC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING)
FROM
    (SELECT 
        TimePeriod,
        SUM(Amount) AS [Total Per Period],
        CAST( ROUND( SUM(Amount) / SUM(SUM(Amount)) OVER () , 3) AS DECIMAL(12,3)) AS [Percentage of Total]
    FROM
        MyDatabase.MyTable
    GROUP BY
        TimePeriod
) t
ORDER BY
    TimePeriod DESC;

A further improvement would be to combine the whole thing into one level:

SELECT
    TimePeriod,
    SUM(Amount) AS [Total Per Period],
    CAST( ROUND(
            SUM(Amount) /
            SUM(SUM(Amount)) OVER ()
          , 3) AS DECIMAL(12,3)) AS [Percentage of Total],
    CAST( ROUND(
            SUM(SUM(Amount)) OVER (ORDER BY TimePeriod DESC ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) /
            SUM(SUM(Amount)) OVER ()
          , 3) AS DECIMAL(12,3))
FROM
    MyDatabase.MyTable
GROUP BY
    TimePeriod
ORDER BY
    TimePeriod DESC;

Note that the results may be slightly different due to rounding.

SQL Fiddle

猛虎独行 2025-01-26 04:05:55

您可能需要使用 [] 来包含列名称,而不是 ' (表示字符串值),我们还需要为子查询提供别名。

SELECT
    TimePeriod,
    [Total Per Period],
    [Percentage of Total],
    SUM([Percentage of Total]) OVER (ORDER BY TimePeriod)
FROM
    (SELECT 
        TimePeriod,
        SUM(Amount) AS 'Total Per Period', 
        CAST( ROUND( SUM(Amount)/(SELECT SUM(Amount) FROM MyDatabase.MyTable),3) AS DECIMAL(12,3)) AS 'Percentage of Total'
    FROM
        MyDatabase.MyTable
    GROUP BY
        TimePeriod) t1
ORDER BY
    TimePeriod DESC

You might need to use [] to contain column name instead of ' which means string value, also we need to give subquery an alias name.

SELECT
    TimePeriod,
    [Total Per Period],
    [Percentage of Total],
    SUM([Percentage of Total]) OVER (ORDER BY TimePeriod)
FROM
    (SELECT 
        TimePeriod,
        SUM(Amount) AS 'Total Per Period', 
        CAST( ROUND( SUM(Amount)/(SELECT SUM(Amount) FROM MyDatabase.MyTable),3) AS DECIMAL(12,3)) AS 'Percentage of Total'
    FROM
        MyDatabase.MyTable
    GROUP BY
        TimePeriod) t1
ORDER BY
    TimePeriod DESC
佞臣 2025-01-26 04:05:55

这是我对你的问题的解决方案。我在Oracle中解决了这个问题。

with flo as (
    select
      timeperiod, 
      sum(amount) as amount,
      cast((sum(amount) / (select sum(amount) from da ))as decimal(10,6)) *100.0 as percent_of_total
    from  yourtable
    group by timeperiod
)
select
  timeperiod,
  amount,
  percent_of_total,
  sum(percent_of_total) over (order by timeperiod desc ) as running
from flo;

This is my solution to your problem. I solve it in Oracle.

with flo as (
    select
      timeperiod, 
      sum(amount) as amount,
      cast((sum(amount) / (select sum(amount) from da ))as decimal(10,6)) *100.0 as percent_of_total
    from  yourtable
    group by timeperiod
)
select
  timeperiod,
  amount,
  percent_of_total,
  sum(percent_of_total) over (order by timeperiod desc ) as running
from flo;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文