SQL 有条件地从行中减去一些数字
SQL deduct some numbers from rows conditionally
我有一个 table(显示温度 table)
CREATE TABLE #TempTable
(
TempID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
CustID INT NOT NULL,
RODate DATE NULL,
Operation INT NULL
);
这个 table 有这个样本数据:
INSERT INTO #TempTable (CustID, RODate, Operation)
VALUES (10, DATEADD(MONT, -2, GETDATE()), 2),
(10, DATEADD(MONT, -1, GETDATE()), 3),
(10, GETDATE(), 5)
所以table有以下数据
TempID CustID RODate Operation
-----------------------------------------------------------
1 10 2019-03-17 2
2 10 2019-04-17 3
3 10 2019-05-17 5
要求我在参数中得到一个整型变量@noOfOperation
,假设它的值为10
我还会得到参数中的月份数,假设是 3
我只需要查询最近 3 个月的 table 到 return 数据(不包括当前月份(日期升序)
然后我必须从 table 中减去 @noOfOperation
并更新。
扣除将基于操作列中的可用性。
例如:本例中我们先从2019-03-17中扣除
10 - 2 = 8 (operation column for this row becomes 0)
接下来我们将从2019-04-17开始扣除
8 - 3 = 5 (operation column for this row becomes 0)
2019-05-17 同样如此
5-5 = 0 (operation column for this row becomes 0)
我必须检查 @noOfOperation
是否小于或大于个别月份的操作次数,然后相应地执行上述操作
看看这个,想法是使用累加运算然后减去所需的值,如下所示:
declare @TempTable TABLE
(
TempID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
CustID INT NOT NULL,
RODate DATE NULL,
Operation INT NULL
);
INSERT INTO @TempTable (CustID, RODate, Operation)
VALUES (10, DATEADD(MONTH, -2, GETDATE()), 5),
(10, DATEADD(MONTH, -1, GETDATE()), 6),
(10, GETDATE(), 7)
select * from @TempTable
Declare @noOfOperation int =8
Declare @noOfMonths int =3
Declare @StartDate date,@DateEnd date,@avNoOfOperation int
--get the range you are working for
select
@StartDate=cast(cast(year(dateadd(Month,-@noOfMonths+1,getdate())) as varchar(4))+'-'+cast(Month(dateadd(Month,-@noOfMonths+1,getdate())) as varchar(2))+'-01' as date)
,@DateEnd=dateadd(day,-1,cast(cast(year(getdate()) as varchar(4))+'-'+cast(Month(getdate()) as varchar(2))+'-01' as date)) ;
--get the total of avaliable operation, for validating before subtracting
select @avNoOfOperation=sum(t.Operation) from @TempTable t where cast(t.RODate as date) between @StartDate and @DateEnd
--review the variables if needed
--select @StartDate [@StartDate],@DateEnd [@DateEnd],@avNoOfOperation [@avNoOfOperation]
if(@avNoOfOperation>=@noOfOperation and @noOfOperation>0)
begin
--only here we can start subtracting
;with DataIncluded as (
select *,@noOfOperation [noOfOperation],sum(Operation) over (order by RODate) [AcOp] from @TempTable t where cast(t.RODate as date) between @StartDate and @DateEnd
),SubtractDataSet as (
select *,AcOp-@noOfOperation [leftOp],
case when (AcOp-@noOfOperation)<=0 then 0 else
case when (AcOp-@noOfOperation)<Operation then AcOp-@noOfOperation else Operation end end [UpOp]
from DataIncluded
)
Update @TempTable
set A.Operation=B.[UpOp]
From @TempTable A
inner join SubtractDataSet B on A.TempID=B.TempID
end
select * from @TempTable
注意:我没有使用当前月份,所以我的输出与您建议的不同。如果输入如下:
TempID CustID RODate Operation
1 10 2019-03-17 5
2 10 2019-04-17 6
3 10 2019-05-17 7
输出将是:-
TempID CustID RODate Operation
1 10 2019-03-17 0
2 10 2019-04-17 3
3 10 2019-05-17 7
--Change the value of @OperationsToBeDeducted, to see different results
declare @OperationsToBeDeducted int
declare @OperationsRemaining int
declare @RODate date
set @OperationsToBeDeducted = 4
declare @TempID int
set @TempID = 1
DROP TABLE IF EXISTS #TempOperation
create table #TempOperation
(
TempID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
CustID INT NOT NULL,
RODate DATE NULL,
Operation INT NULL
);
insert into #TempOperation (CustID,RODate,Operation)
values
(10,DATEADD(month, -3, getdate()),2),
(10,DATEADD(month, -2, getdate()), 2),
(10,DATEADD(month, -1, getdate()),3)
DROP TABLE IF EXISTS #TempOperation2
create table #TempOperation2
(
TempID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
CustID INT NOT NULL,
RODate DATE NULL,
Operation INT NULL
);
insert into #TempOperation2 select CustID,RODate, Operation from #TempOperation
select * from #TempOperation2 order by RODate asc
declare @maxID int;
select @maxID = max(TempID) from #TempOperation2
while (@TempID <= @maxID)
begin
set @OperationsRemaining = 0
select @OperationsRemaining = Operation, @RODate = RODate from #TempOperation2 where TempID = @TempID
if(@OperationsToBeDeducted is not null and @OperationsRemaining is not null and
@OperationsRemaining > 0 and @OperationsRemaining > @OperationsToBeDeducted)
begin
update #TempOperation set Operation = @OperationsRemaining - @OperationsToBeDeducted where TempID = @TempID
set @OperationsToBeDeducted = 0
end
else if(@OperationsToBeDeducted is not null and @OperationsRemaining is not null and
@OperationsRemaining > 0 and @OperationsRemaining <= @OperationsToBeDeducted)
begin
set @OperationsToBeDeducted = @OperationsToBeDeducted - @OperationsRemaining
update #TempOperation set Operation = @OperationsRemaining - @OperationsRemaining where TempID = @TempID
end
SET @TempID = @TempID + 1
end
select * from #TempOperation order by RODate asc
DROP TABLE #TempOperation
DROP TABLE #TempOperation2
我有一个 table(显示温度 table)
CREATE TABLE #TempTable
(
TempID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
CustID INT NOT NULL,
RODate DATE NULL,
Operation INT NULL
);
这个 table 有这个样本数据:
INSERT INTO #TempTable (CustID, RODate, Operation)
VALUES (10, DATEADD(MONT, -2, GETDATE()), 2),
(10, DATEADD(MONT, -1, GETDATE()), 3),
(10, GETDATE(), 5)
所以table有以下数据
TempID CustID RODate Operation
-----------------------------------------------------------
1 10 2019-03-17 2
2 10 2019-04-17 3
3 10 2019-05-17 5
要求我在参数中得到一个整型变量@noOfOperation
,假设它的值为10
我还会得到参数中的月份数,假设是 3
我只需要查询最近 3 个月的 table 到 return 数据(不包括当前月份(日期升序)
然后我必须从 table 中减去 @noOfOperation
并更新。
扣除将基于操作列中的可用性。
例如:本例中我们先从2019-03-17中扣除
10 - 2 = 8 (operation column for this row becomes 0)
接下来我们将从2019-04-17开始扣除
8 - 3 = 5 (operation column for this row becomes 0)
2019-05-17 同样如此
5-5 = 0 (operation column for this row becomes 0)
我必须检查 @noOfOperation
是否小于或大于个别月份的操作次数,然后相应地执行上述操作
看看这个,想法是使用累加运算然后减去所需的值,如下所示:
declare @TempTable TABLE
(
TempID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
CustID INT NOT NULL,
RODate DATE NULL,
Operation INT NULL
);
INSERT INTO @TempTable (CustID, RODate, Operation)
VALUES (10, DATEADD(MONTH, -2, GETDATE()), 5),
(10, DATEADD(MONTH, -1, GETDATE()), 6),
(10, GETDATE(), 7)
select * from @TempTable
Declare @noOfOperation int =8
Declare @noOfMonths int =3
Declare @StartDate date,@DateEnd date,@avNoOfOperation int
--get the range you are working for
select
@StartDate=cast(cast(year(dateadd(Month,-@noOfMonths+1,getdate())) as varchar(4))+'-'+cast(Month(dateadd(Month,-@noOfMonths+1,getdate())) as varchar(2))+'-01' as date)
,@DateEnd=dateadd(day,-1,cast(cast(year(getdate()) as varchar(4))+'-'+cast(Month(getdate()) as varchar(2))+'-01' as date)) ;
--get the total of avaliable operation, for validating before subtracting
select @avNoOfOperation=sum(t.Operation) from @TempTable t where cast(t.RODate as date) between @StartDate and @DateEnd
--review the variables if needed
--select @StartDate [@StartDate],@DateEnd [@DateEnd],@avNoOfOperation [@avNoOfOperation]
if(@avNoOfOperation>=@noOfOperation and @noOfOperation>0)
begin
--only here we can start subtracting
;with DataIncluded as (
select *,@noOfOperation [noOfOperation],sum(Operation) over (order by RODate) [AcOp] from @TempTable t where cast(t.RODate as date) between @StartDate and @DateEnd
),SubtractDataSet as (
select *,AcOp-@noOfOperation [leftOp],
case when (AcOp-@noOfOperation)<=0 then 0 else
case when (AcOp-@noOfOperation)<Operation then AcOp-@noOfOperation else Operation end end [UpOp]
from DataIncluded
)
Update @TempTable
set A.Operation=B.[UpOp]
From @TempTable A
inner join SubtractDataSet B on A.TempID=B.TempID
end
select * from @TempTable
注意:我没有使用当前月份,所以我的输出与您建议的不同。如果输入如下:
TempID CustID RODate Operation
1 10 2019-03-17 5
2 10 2019-04-17 6
3 10 2019-05-17 7
输出将是:-
TempID CustID RODate Operation
1 10 2019-03-17 0
2 10 2019-04-17 3
3 10 2019-05-17 7
--Change the value of @OperationsToBeDeducted, to see different results
declare @OperationsToBeDeducted int
declare @OperationsRemaining int
declare @RODate date
set @OperationsToBeDeducted = 4
declare @TempID int
set @TempID = 1
DROP TABLE IF EXISTS #TempOperation
create table #TempOperation
(
TempID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
CustID INT NOT NULL,
RODate DATE NULL,
Operation INT NULL
);
insert into #TempOperation (CustID,RODate,Operation)
values
(10,DATEADD(month, -3, getdate()),2),
(10,DATEADD(month, -2, getdate()), 2),
(10,DATEADD(month, -1, getdate()),3)
DROP TABLE IF EXISTS #TempOperation2
create table #TempOperation2
(
TempID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
CustID INT NOT NULL,
RODate DATE NULL,
Operation INT NULL
);
insert into #TempOperation2 select CustID,RODate, Operation from #TempOperation
select * from #TempOperation2 order by RODate asc
declare @maxID int;
select @maxID = max(TempID) from #TempOperation2
while (@TempID <= @maxID)
begin
set @OperationsRemaining = 0
select @OperationsRemaining = Operation, @RODate = RODate from #TempOperation2 where TempID = @TempID
if(@OperationsToBeDeducted is not null and @OperationsRemaining is not null and
@OperationsRemaining > 0 and @OperationsRemaining > @OperationsToBeDeducted)
begin
update #TempOperation set Operation = @OperationsRemaining - @OperationsToBeDeducted where TempID = @TempID
set @OperationsToBeDeducted = 0
end
else if(@OperationsToBeDeducted is not null and @OperationsRemaining is not null and
@OperationsRemaining > 0 and @OperationsRemaining <= @OperationsToBeDeducted)
begin
set @OperationsToBeDeducted = @OperationsToBeDeducted - @OperationsRemaining
update #TempOperation set Operation = @OperationsRemaining - @OperationsRemaining where TempID = @TempID
end
SET @TempID = @TempID + 1
end
select * from #TempOperation order by RODate asc
DROP TABLE #TempOperation
DROP TABLE #TempOperation2