运行 总和整数值分配
Running Total and Integer Value Allocation
我需要能够确定每一行的剩余点分配量。让我解释以下查询:
变量
- @allocated int --> 已经分配点数
- @to_allocate int --> 我们现在需要分配的点
查看"audits"
- ts --> 收集点数的日期
- points --> 收集的点数
到目前为止,我只能在 "audits" 中的数据是这样的情况下才能得到正确的结果:
这个有效
IF OBJECT_ID('audits') IS NOT NULL
DROP VIEW audits;
GO
CREATE VIEW audits
AS
SELECT '2000-1-1' AS ts, 10 AS points UNION ALL
SELECT '2000-1-2' AS ts, 12 AS points UNION ALL
SELECT '2000-1-3' AS ts, 123 AS points UNION ALL
SELECT '2000-1-4' AS ts, 100 AS points;
GO
不起作用
CREATE VIEW audits
AS
SELECT '2000-1-1' AS ts, 106 AS points UNION ALL
SELECT '2000-1-2' AS ts, 12 AS points UNION ALL
SELECT '2000-1-3' AS ts, 123 AS points UNION ALL
SELECT '2000-1-4' AS ts, 100 AS points;
GO
查询
DECLARE @to_allocate int = 92;
DECLARE @allocated int = 4;
WITH result
AS
(
SELECT
ts,
points,
SUM(points) OVER(ORDER BY ts) AS total
FROM audits
),
points
AS
(
SELECT
ts,
points,
total,
CASE
WHEN @to_allocate > total - @allocated THEN total - @allocated
ELSE @to_allocate - SUM(total - @allocated)
OVER(ORDER BY ts ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
END as result
FROM result
)
SELECT * FROM points
WHERE result > 0;
"Does not work" 数据的期望输出
请注意,结果列中的值不应大于相应行的点。因此,
- 当@to_allocate 为 92
- 当@to_allocate 为 200
我可以通过使用临时表和循环来解决这个问题,但这是我不想做的事情,因为它阻止我在函数上使用它。任何帮助或指出正确的方向将不胜感激。
是这样的吗?
DECLARE @to_allocate int = 200
DECLARE @allocated int = 4
select *,
points -
case when total < @allocated then points
when prev < @allocated then @allocated - prev
else 0
end -
case when total > @to_allocate + @allocated
then total - @to_allocate - @allocated
else 0
end
from
(
select *, lag(total, 1, 0) over (order by ts asc) as prev
from
(
select *, sum(points) over (order by ts asc) as total from audits
) X
) X
where prev < @to_allocate + @allocated
我假设 @allocated 必须从不仅仅是第一行中删除值,尽管你的例子只有那个。
我需要能够确定每一行的剩余点分配量。让我解释以下查询:
变量
- @allocated int --> 已经分配点数
- @to_allocate int --> 我们现在需要分配的点
查看"audits"
- ts --> 收集点数的日期
- points --> 收集的点数
到目前为止,我只能在 "audits" 中的数据是这样的情况下才能得到正确的结果:
这个有效
IF OBJECT_ID('audits') IS NOT NULL
DROP VIEW audits;
GO
CREATE VIEW audits
AS
SELECT '2000-1-1' AS ts, 10 AS points UNION ALL
SELECT '2000-1-2' AS ts, 12 AS points UNION ALL
SELECT '2000-1-3' AS ts, 123 AS points UNION ALL
SELECT '2000-1-4' AS ts, 100 AS points;
GO
不起作用
CREATE VIEW audits
AS
SELECT '2000-1-1' AS ts, 106 AS points UNION ALL
SELECT '2000-1-2' AS ts, 12 AS points UNION ALL
SELECT '2000-1-3' AS ts, 123 AS points UNION ALL
SELECT '2000-1-4' AS ts, 100 AS points;
GO
查询
DECLARE @to_allocate int = 92;
DECLARE @allocated int = 4;
WITH result
AS
(
SELECT
ts,
points,
SUM(points) OVER(ORDER BY ts) AS total
FROM audits
),
points
AS
(
SELECT
ts,
points,
total,
CASE
WHEN @to_allocate > total - @allocated THEN total - @allocated
ELSE @to_allocate - SUM(total - @allocated)
OVER(ORDER BY ts ROWS BETWEEN UNBOUNDED PRECEDING AND 1 PRECEDING)
END as result
FROM result
)
SELECT * FROM points
WHERE result > 0;
"Does not work" 数据的期望输出
请注意,结果列中的值不应大于相应行的点。因此,
- 当@to_allocate 为 92
- 当@to_allocate 为 200
我可以通过使用临时表和循环来解决这个问题,但这是我不想做的事情,因为它阻止我在函数上使用它。任何帮助或指出正确的方向将不胜感激。
是这样的吗?
DECLARE @to_allocate int = 200
DECLARE @allocated int = 4
select *,
points -
case when total < @allocated then points
when prev < @allocated then @allocated - prev
else 0
end -
case when total > @to_allocate + @allocated
then total - @to_allocate - @allocated
else 0
end
from
(
select *, lag(total, 1, 0) over (order by ts asc) as prev
from
(
select *, sum(points) over (order by ts asc) as total from audits
) X
) X
where prev < @to_allocate + @allocated
我假设 @allocated 必须从不仅仅是第一行中删除值,尽管你的例子只有那个。