计算 SQL 中年初至今数字的周期值
Calculate periodic values from year to date figures in SQL
我已经累积了每个时期的年初至今值。
但是我需要每个产品组/周期的周期值。
您是否知道 SQL 服务器中的解决方案以简单的方式实现此目的?
这是我的示例数据:
Product Group | Period | Amount
-------------------------------
Group 1 |2018/01 | 500
Group 1 |2018/02 | 740
Group 1 |2018/03 | 900
Group 1 |2018/04 | 930
结果应该是这样的:
Product Group | Period | Amount
-------------------------------
Group 1 |2018/01 | 500
Group 1 |2018/02 | 240
Group 1 |2018/03 | 160
Group 1 |2018/04 | 30
感谢您的帮助!
菲利普
您可以像这样使用 LAG 函数:
SELECT [Product Group], Period,
Amount - LAG(Amount, 1,0) OVER (ORDER BY Period) AS Amount
FROM myTable
希望对您有所帮助:
Select
ProductGroup,
Period,
Amount = Amount-ISNULL((Select Amount from TempTable where Period = (select max(Period) from TempTable where Period < Main.Period)),0)
From TempTable Main
Order by Period
我假设 Period 是日期时间类型 (2018-01-01)
查询中的一个小改动
SELECT [ProductGroup], Period,
Amount- LAG(Amount, 1,0) OVER (ORDER BY Period) AS Amount
FROM tablename
希望对你有所帮助
WITH CTE AS (
SELECT
rownum = ROW_NUMBER() OVER (ORDER BY t.[Product Group],t.[Period]),
t.*
FROM YourTbl AS t
)
SELECT CTE.[Product Group],CTE.Period,-1*(ISNULL(prev.Amount,0)-CTE.Amount) AS Amount
FROM CTE
LEFT JOIN CTE prev ON prev.rownum = CTE.rownum - 1
假设您不能使用 LAG(例如 MSSQL 2008)并且每个 ProductGroup 和 Period 可以有多个记录,您可以使用以下查询。
示例 table 和值:
CREATE TABLE GR (Product_Group VARCHAR(10), Period VARCHAR(6), Amount INT);
INSERT INTO GR VALUES ('Group 1', '201801', 500)
, ('Group 1', '201802', 740)
,('Group 1', '201803', 900)
,('Group 1', '201804', 930)
;
INSERT INTO GR VALUES ('Group 2', '201801', 500)
, ('Group 2', '201803', 800)
,('Group 2', '201803', 1000)
,('Group 2', '201804', 1200)
;
查询使用 GROUP BY(和 CTE 以简化阅读)对 ProductGroup 和 Period 进行分组,并使用 RowNumber 来查找以前的值(如果你有固定的时间段,即如果你想在月份值时显示每个月的记录缺少您可以使用理货日期 table)
WITH X AS (SELECT Product_Group, Period, SUM(Amount) AS Amount_TOT
, ROW_NUMBER() OVER (PARTITION BY Product_Group ORDER BY PERIOD) AS RN
FROM GR GROUP BY Product_group, Period)
SELECT Product_Group, Period, Amount_TOT, Amount_TOT_PREC, Amount_TOT-ISNULL(Amount_TOT_PREC,0) AS Delta
FROM (SELECT A.Product_Group, A.Period, A.Amount_TOT, B.Amount_TOT AS Amount_TOT_PREC
FROM X A
LEFT JOIN X B ON A.Product_Group=B.Product_Group AND A.RN-1 = B.RN
) C
输出
+---------------+--------+------------+-----------------+-------+
| Product_Group | Period | Amount_TOT | Amount_TOT_PREC | Delta |
+---------------+--------+------------+-----------------+-------+
| Group 1 | 201801 | 500 | NULL | 500 |
| Group 1 | 201802 | 740 | 500 | 240 |
| Group 1 | 201803 | 900 | 740 | 160 |
| Group 1 | 201804 | 930 | 900 | 30 |
| Group 2 | 201801 | 500 | NULL | 500 |
| Group 2 | 201803 | 1800 | 500 | 1300 |
| Group 2 | 201804 | 1200 | 1800 | -600 |
+---------------+--------+------------+-----------------+-------+
使用 LAG(此函数 return 先前记录的值,请查看 Microsoft 文档)更快且更易读:
WITH X AS (SELECT Product_Group, Period
, SUM(Amount) AS Amount_TOT
FROM GR GROUP BY Product_group, Period)
SELECT Product_Group, Period, Amount_TOT, AMOUNT_PREC
, Amount_TOT-ISNULL(AMOUNT_PREC,0) AS Delta
FROM (SELECT Product_Group, Period, Amount_TOT
, LAG(Amount_TOT) OVER (PARTITION BY Product_Group
ORDER BY PERIOD) AS AMOUNT_PREC
FROM X) A;
与上面相同的输出
我会使用 lag()
函数:
select [Product Group], Period,
Amount - LAG(Amount, 1,0) OVER (ORDER BY Period) AS Amount
from table t'
如果你有旧版本的 SQL,那么你也可以使用 apply
:
select t.product, t.period, coalesce(t.amount-t1.amount, t.amount) as amount
from table t outer apply
( select top (1) t1.*
from table t1
where t1.product = t.product and
t1.period < t.period
order by t1.period desc
) t1;
我已经累积了每个时期的年初至今值。 但是我需要每个产品组/周期的周期值。
您是否知道 SQL 服务器中的解决方案以简单的方式实现此目的?
这是我的示例数据:
Product Group | Period | Amount
-------------------------------
Group 1 |2018/01 | 500
Group 1 |2018/02 | 740
Group 1 |2018/03 | 900
Group 1 |2018/04 | 930
结果应该是这样的:
Product Group | Period | Amount
-------------------------------
Group 1 |2018/01 | 500
Group 1 |2018/02 | 240
Group 1 |2018/03 | 160
Group 1 |2018/04 | 30
感谢您的帮助! 菲利普
您可以像这样使用 LAG 函数:
SELECT [Product Group], Period,
Amount - LAG(Amount, 1,0) OVER (ORDER BY Period) AS Amount
FROM myTable
希望对您有所帮助:
Select
ProductGroup,
Period,
Amount = Amount-ISNULL((Select Amount from TempTable where Period = (select max(Period) from TempTable where Period < Main.Period)),0)
From TempTable Main
Order by Period
我假设 Period 是日期时间类型 (2018-01-01)
查询中的一个小改动
SELECT [ProductGroup], Period,
Amount- LAG(Amount, 1,0) OVER (ORDER BY Period) AS Amount
FROM tablename
希望对你有所帮助
WITH CTE AS (
SELECT
rownum = ROW_NUMBER() OVER (ORDER BY t.[Product Group],t.[Period]),
t.*
FROM YourTbl AS t
)
SELECT CTE.[Product Group],CTE.Period,-1*(ISNULL(prev.Amount,0)-CTE.Amount) AS Amount
FROM CTE
LEFT JOIN CTE prev ON prev.rownum = CTE.rownum - 1
假设您不能使用 LAG(例如 MSSQL 2008)并且每个 ProductGroup 和 Period 可以有多个记录,您可以使用以下查询。
示例 table 和值:
CREATE TABLE GR (Product_Group VARCHAR(10), Period VARCHAR(6), Amount INT);
INSERT INTO GR VALUES ('Group 1', '201801', 500)
, ('Group 1', '201802', 740)
,('Group 1', '201803', 900)
,('Group 1', '201804', 930)
;
INSERT INTO GR VALUES ('Group 2', '201801', 500)
, ('Group 2', '201803', 800)
,('Group 2', '201803', 1000)
,('Group 2', '201804', 1200)
;
查询使用 GROUP BY(和 CTE 以简化阅读)对 ProductGroup 和 Period 进行分组,并使用 RowNumber 来查找以前的值(如果你有固定的时间段,即如果你想在月份值时显示每个月的记录缺少您可以使用理货日期 table)
WITH X AS (SELECT Product_Group, Period, SUM(Amount) AS Amount_TOT
, ROW_NUMBER() OVER (PARTITION BY Product_Group ORDER BY PERIOD) AS RN
FROM GR GROUP BY Product_group, Period)
SELECT Product_Group, Period, Amount_TOT, Amount_TOT_PREC, Amount_TOT-ISNULL(Amount_TOT_PREC,0) AS Delta
FROM (SELECT A.Product_Group, A.Period, A.Amount_TOT, B.Amount_TOT AS Amount_TOT_PREC
FROM X A
LEFT JOIN X B ON A.Product_Group=B.Product_Group AND A.RN-1 = B.RN
) C
输出
+---------------+--------+------------+-----------------+-------+
| Product_Group | Period | Amount_TOT | Amount_TOT_PREC | Delta |
+---------------+--------+------------+-----------------+-------+
| Group 1 | 201801 | 500 | NULL | 500 |
| Group 1 | 201802 | 740 | 500 | 240 |
| Group 1 | 201803 | 900 | 740 | 160 |
| Group 1 | 201804 | 930 | 900 | 30 |
| Group 2 | 201801 | 500 | NULL | 500 |
| Group 2 | 201803 | 1800 | 500 | 1300 |
| Group 2 | 201804 | 1200 | 1800 | -600 |
+---------------+--------+------------+-----------------+-------+
使用 LAG(此函数 return 先前记录的值,请查看 Microsoft 文档)更快且更易读:
WITH X AS (SELECT Product_Group, Period
, SUM(Amount) AS Amount_TOT
FROM GR GROUP BY Product_group, Period)
SELECT Product_Group, Period, Amount_TOT, AMOUNT_PREC
, Amount_TOT-ISNULL(AMOUNT_PREC,0) AS Delta
FROM (SELECT Product_Group, Period, Amount_TOT
, LAG(Amount_TOT) OVER (PARTITION BY Product_Group
ORDER BY PERIOD) AS AMOUNT_PREC
FROM X) A;
与上面相同的输出
我会使用 lag()
函数:
select [Product Group], Period,
Amount - LAG(Amount, 1,0) OVER (ORDER BY Period) AS Amount
from table t'
如果你有旧版本的 SQL,那么你也可以使用 apply
:
select t.product, t.period, coalesce(t.amount-t1.amount, t.amount) as amount
from table t outer apply
( select top (1) t1.*
from table t1
where t1.product = t.product and
t1.period < t.period
order by t1.period desc
) t1;