Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
SQL Server-在几个月内拆分一个值而不使用游标_Sql_Sql Server - Fatal编程技术网

SQL Server-在几个月内拆分一个值而不使用游标

SQL Server-在几个月内拆分一个值而不使用游标,sql,sql-server,Sql,Sql Server,如果某个值(X)超过值(Y),是否可以在几个月内拆分该值(X),而不使用光标 例如,我有一个值X=505,我想把它分成尽可能多的几个月,每个月的最大值为100(值Y=100) 因此,我的预期输出是: JAN 100 FEB 100 MAR 100 APR 100 MAY 100 JUN 5 我不关心重叠(6月的第5行),如果没有重叠也是可以的。您能使用TOP X(rows)语法吗?如果要生成SQL查询字符串,可以使用: 挑选 顶部(505/100) *

如果某个值(X)超过值(Y),是否可以在几个月内拆分该值(X),而不使用光标

例如,我有一个值X=505,我想把它分成尽可能多的几个月,每个月的最大值为100(值Y=100)

因此,我的预期输出是:

JAN    100
FEB    100
MAR    100
APR    100
MAY    100
JUN      5
我不关心重叠(6月的第5行),如果没有重叠也是可以的。

您能使用TOP X(rows)语法吗?如果要生成SQL查询字符串,可以使用:

挑选 顶部(505/100) * 从桌子上

所以505/100舍入为整数,只得到5行


然后,您需要连接到日历表以获取月份

您可以使用数字表,使用交叉应用将值分散在一系列月份上,如下所示

create table T(
  id int,
  dat datetime,
  val int,
  primary key(id, dat)
);

insert into T values (1, '20140101', 100);
insert into T values (2, '20140101', 99);
insert into T values (3, '20140201', 274);
insert into T values (4, '20140301', 300);

declare @chunk int = 100;
select
  id,
  dateadd(month,n-1,dat) as dat,
  case when n=max(n) over (partition by id) then (val-1)%@chunk+1 else @chunk end as val
from T
cross apply (
  select n from Nums
  where n <= ceiling((val+@chunk-1)/@chunk)
) as N(n);
(如果值不是整数,则需要稍微调整。)

如果手头没有1到1024的数字表,这里有一些SQL来创建一个数字表

create table Nums(
  n int primary key
)
insert into Nums values (1);
declare @i int = 10;
while @i>0 begin
  insert into Nums
    select max(n) over () + n
  from Nums;
  set @i -= 1;
end;

一点数学有帮助,一点数学。
使用Steve Kass答案中的表格

declare @chunk int = 100;

WITH Base(N) AS (
  SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
  SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
  SELECT 1 UNION ALL SELECT 1
), Base10(N) AS (
  SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) - 1
  FROM Base
), Counter(N) AS (
  SELECT u.N + 10*t.N
  FROM   Base10 u
         CROSS JOIN Base10 t
)
SELECT id
     , DateAdd(MONTH, N, dat) Month
     , Cast((val - (@chunk * N)) / @chunk as BIT) * @chunk
     + (1 - Cast((val - (@chunk * N)) / @chunk as BIT)) * (val % @chunk) Value
FROM   T
       LEFT JOIN Counter ON N < CEILING(Cast(val as Float) / @chunk)
val列被强制转换为浮点以防止整数除法,我使用了
左连接
而不是
交叉连接
,以便能够在那里添加条件,而不是在
WHERE
条件中添加条件

demo,在demo中,区块是静态的

declare @chunk int = 100;

WITH Base(N) AS (
  SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
  SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL 
  SELECT 1 UNION ALL SELECT 1
), Base10(N) AS (
  SELECT (ROW_NUMBER() OVER (ORDER BY (SELECT NULL))) - 1
  FROM Base
), Counter(N) AS (
  SELECT u.N + 10*t.N
  FROM   Base10 u
         CROSS JOIN Base10 t
)
SELECT id
     , DateAdd(MONTH, N, dat) Month
     , Cast((val - (@chunk * N)) / @chunk as BIT) * @chunk
     + (1 - Cast((val - (@chunk * N)) / @chunk as BIT)) * (val % @chunk) Value
FROM   T
       LEFT JOIN Counter ON N < CEILING(Cast(val as Float) / @chunk)
IF (val - (100 * N) / 100) > 0 THEN
  RETURN 100
ELSE
  RETURN VAL % 100
END IF