use*_*140 3 sql-server t-sql sql-server-2008-r2
我看到@ypercube 的回答??这对如何计算似乎是由 3 订购的数量并给出整数答案给出了很好的答案。这让我想到,如果要拆分的次数可变,您将如何处理?
这意味着这是你总是会被 3 分割的 OP(原始海报
Create Table #Orders
(
id int IDENTITY(1,1) PRIMARY KEY NOT NULL
,partid varchar(100) NOT NULL
,qtyordered int DEFAULT '0'
,orderedby varchar(100) NOT NULL
,ordereddate date DEFAULT GETDATE()
) ;
Insert Into #Orders (partid, qtyordered, orderedby) VALUES
('SS100', 10, 'James'), ('RR200', 5, 'Bob'), ('NN300', 3, 'Jake'), ('OO400', 5, 'Blue') ;
SELECT
partid,
qtyordered,
[First],
[Second],
[Third]
FROM
#Orders
CROSS APPLY
( SELECT [Third] = (qtyordered) / 3 ) AS q3
CROSS APPLY
( SELECT [Second] = (qtyordered - [Third]) / 2 ) AS q2
CROSS APPLY
( SELECT [First] = (qtyordered - [Third] - [Second]) / 1 ) AS q1;
Run Code Online (Sandbox Code Playgroud)
dbfiddle在这里
但是,如果不是总是被 3 分割,而是有一个 int 变量来说明要分割的次数,比如说相同的 DDL 但不是被 3 分割,而是使用
Declare @TTS int = 5
Run Code Online (Sandbox Code Playgroud)
现在您将每个场景拆分为 5 种方式而不是 3 种方式。基本上是一个可重用的函数,可以根据变量“即时”拆分?
基本上,我们只是想将除法中的余数分散到值上。这个过程正是这样做的;它将返回一个表,其中包含拆分的结果 vals。我假设我们不想返回可变数量的列(取决于我们收到的除数),我决定实际生成文本“第一”、“第二”等并不是问题的一部分,所以我在自己的行中返回每个值。
CREATE PROCEDURE split_into_ints(@dividend int, @divisor int)
AS
BEGIN
WITH result_rows AS
(SELECT TOP (@divisor) ROW_NUMBER() OVER (ORDER BY o1.object_id)
as result_num
FROM sys.objects o1 CROSS JOIN sys.objects o2
)
,base_vals AS
(SELECT @dividend / @divisor as base_result
,@dividend % @divisor as remainder
)
SELECT r.result_num
,CASE WHEN r.result_num <= remainder THEN 1 ELSE 0 END
+ v.base_result as result_val
FROM base_vals v CROSS JOIN result_rows r
ORDER BY result_num
END;
GO
Run Code Online (Sandbox Code Playgroud)
下列:
EXECUTE split_into_ints 10,3;
EXECUTE split_into_ints 49,6;
EXECUTE split_into_ints 2000,11;
Run Code Online (Sandbox Code Playgroud)
产生这些结果:
result_num result_val
-------------------- -----------
1 4
2 3
3 3
result_num result_val
-------------------- -----------
1 9
2 8
3 8
4 8
5 8
6 8
result_num result_val
-------------------- -----------
1 182
2 182
3 182
4 182
5 182
6 182
7 182
8 182
9 182
10 181
11 181
Run Code Online (Sandbox Code Playgroud)
或者,您可以将其设为内联表值函数:
CREATE FUNCTION fn_split_into_ints(@dividend int, @divisor int)
RETURNS TABLE
AS
RETURN
(
WITH result_rows AS
(SELECT TOP (@divisor) ROW_NUMBER() OVER (ORDER BY o1.object_id)
as result_num
FROM sys.objects o1 CROSS JOIN sys.objects o2
)
,base_vals AS
(SELECT @dividend / @divisor as base_result
,@dividend % @divisor as remainder
)
SELECT r.result_num
,CASE WHEN r.result_num <= remainder THEN 1 ELSE 0 END
+ v.base_result as result_val
FROM base_vals v CROSS JOIN result_rows r
);
GO
Run Code Online (Sandbox Code Playgroud)
因此,您运行与上述相同的查询:
SELECT * FROM fn_split_into_ints(10,3);
SELECT * FROM fn_split_into_ints(49,6);
SELECT * FROM fn_split_into_ints(2000,11);
Run Code Online (Sandbox Code Playgroud)
结果是一样的。回答一个评论:这将允许您result_val
进入一个变量:
SELECT @result_val = result_val
FROM fn_split_into_ints(49,6)
WHERE result_num = 6
;
Run Code Online (Sandbox Code Playgroud)
编辑:更改了函数名称,因此函数和过程可以共存(如果您希望它们共存,出于某种原因)。
归档时间: |
|
查看次数: |
131 次 |
最近记录: |