计算 SQL 查询中的百分比

时间:2021-06-13 22:22:44

标签: sql sql-server tsql

我在 SQL 中有一个表,它有两列数据,第一个是周数,第二个是一个值。同一周可以有多个记录。这是一些示例数据(我在最后为这些数据添加了一些 SQL):

<头>
id WeekNo MyAmount
1 1 5200.00
2 1 180.00
3 1 100.00
4 2 100.00
5 2 50.00
6 3 100.00
7 3 100.00
8 4 100.00
9 4 900.00
10 4 1000.00

我有一个按周对这些值求和的查询,并添加另一列包含所有周的累积值。这工作正常

with data as (
    SELECT WeekNo,
           SUM(MyAmount) As TheAmount
    FROM #tTryIt
    GROUP BY WeekNo
    )

SELECT WeekNo, 
       TheAmount,
       SUM(TheAmount) over (order by WeekNo asc rows between unbounded preceding and current row) as Cumulative
FROM data 
<头>
WeekNo TheAmount 累积
1 5480.00 5480.00
2 150.00 5630.00
3 200.00 5830.00
4 2000.00 7830.00

现在我想要做的是根据累积计算每周的价值百分比,但也包括前一周(例如,如果在第 2 周,第 2 周的值为 25%,则第 1 周的值必须为 75%累计总数),但到目前为止我只能计算本周的百分比,而不是前一周。

这是我当前的查询和结果:

with data as (
    SELECT WeekNo,
           SUM(MyAmount) As TheAmount
    FROM #tTryIt
    GROUP BY WeekNo
    )

SELECT WeekNo, 
       TheAmount,
       SUM(TheAmount) over (order by WeekNo asc rows between unbounded preceding and current row) as Cumulative,
       (TheAmount/SUM(TheAmount) over (order by WeekNo asc rows between unbounded preceding and current row))*100 as WeekPct
FROM data 
<头>
WeekNo TheAmount 累积 WeekPct
1 5480.00 5480.00 100.000000
2 150.00 5630.00 2.664200
3 200.00 5830.00 3.430500
4 2000.00 7830.00 25.542700

但我真正需要的是这样的(其中 WeekNo 是累计总数的实际周,而 PctWeek 是我们计算百分比的那一周):< /p>

<头>
WeekNo PctWeek TheAmount 累积 WeekPct
1 1 5480.00 5480.00 100.0000
2 1 5480.00 5630.00 97.3358
2 2 150.00 5630.00 2.6642
3 1 5480.00 5830.00 93.9966
3 2 150.00 5830.00 2.5729
3 3 200.00 5830.00 3.4305
4 1 5480.00 7830.00 69.9872
4 2 150.00 7830.00 1.9157
4 3 200.00 7830.00 2.5544
4 4 2000.00 7830.00 25.5427

我怎样才能真正让我的查询输出我需要的数据?


下面的示例 SQL 数据

CREATE TABLE #tTryIt
(
    id INT PRIMARY KEY,
    WeekNo INT,
    MyAmount DECIMAL(18,2)
)

INSERT INTO #tTryIt

VALUES  (1, 1, 5200),
        (2, 1, 180),
        (3, 1, 100),
        (4, 2, 100),
        (5, 2, 50),
        (6, 3, 100),
        (7, 3, 100),
        (8, 4, 100),
        (9, 4, 900),
        (10, 4, 1000);

2 个答案:

答案 0 :(得分:1)

我想这就是你要找的。这里的关键是要注意基数在增加,这意味着某种连接是必要的。

   with thedata as (
    SELECT WeekNo,
           SUM(MyAmount) As TheAmount
    FROM tTryIt
    GROUP BY WeekNo
    )
    SELECT t1.WeekNo, 
           t2.WeekNo as PctWeek, 
           t2.TheAmount,
           SUM(if(t2.WeekNo=1,t1.TheAmount,0)) over (order by t1.WeekNo, t2.WeekNo asc rows between unbounded preceding and current row) as Cumulative,
           t2.TheAmount/(SUM(if(t2.WeekNo=1,t1.TheAmount,0)) over (order by t1.WeekNo, t2.WeekNo asc rows between unbounded preceding and current row))*100 as WeekPct
    FROM thedata as t1 inner join thedata as t2 on (t2.WeekNo<=t1.WeekNo)
    order by t1.WeekNo, t2.WeekNo
    ;

这似乎产生了您要求的表格:

| weekno | pctweek | theamount | cumulative | weekpct           |
+--------+---------+-----------+------------+-------------------+
| 1      | 1       | 5480      | 5480       | 100               |
| 2      | 1       | 5480      | 5630       | 97.33570159857904 |
| 2      | 2       | 150       | 5630       | 2.664298401420959 |
| 3      | 1       | 5480      | 5830       | 93.99656946826758 |
| 3      | 2       | 150       | 5830       | 2.572898799313894 |
| 3      | 3       | 200       | 5830       | 3.430531732418525 |
| 4      | 1       | 5480      | 7830       | 69.98722860791827 |
| 4      | 2       | 150       | 7830       | 1.915708812260536 |
| 4      | 3       | 200       | 7830       | 2.554278416347382 |
| 4      | 4       | 2000      | 7830       | 25.54278416347382 |

答案 1 :(得分:1)

基本上,您可以接受您的查询,然后在所有周内再次加入。这为您提供了前三列。您可以使用窗口函数填写最后两个:

with data as (
      SELECT WeekNo, SUM(MyAmount) As TheAmount
      FROM TryIt
      GROUP BY WeekNo
     )
select w.weekno, d.weekno as pctweek, d.theamount,
       sum(d.theamount) over (partition by w.weekno) as cumulative,
       d.theamount * 100.0 / sum(d.theamount) over (partition by w.weekno)  as pct
from data d join
     (select distinct weekno from TryIt) w
     on d.weekno <= w.weekno
order by 1, 2;

Here 是一个 db<>fiddle。