Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/22.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 根据结果从WHILE循环中的另一个表中进行选择_Sql Server_Tsql_Dynamic Sql_Sp Executesql - Fatal编程技术网

Sql server 根据结果从WHILE循环中的另一个表中进行选择

Sql server 根据结果从WHILE循环中的另一个表中进行选择,sql-server,tsql,dynamic-sql,sp-executesql,Sql Server,Tsql,Dynamic Sql,Sp Executesql,基本上,我试图根据轮班和输入的天数计算用户可以拥有的总小时数 例如: 2020年9月13日开始换班。根据其他计算,我知道这是第一周,周日。 所以我需要把星期天的2号,然后第二周的3,2,1,1,2号放到轮值桌上 总共7天: 第1周=星期日 第2周=周一、周二、周三、周四、周五、周六 ROTA table +------+-----+-----+-----+-----+-----+-----+-----+ | WEEK | MON | TUE | WED | THU | FRI | SAT |

基本上,我试图根据轮班和输入的天数计算用户可以拥有的总小时数

例如: 2020年9月13日开始换班。根据其他计算,我知道这是第一周,周日。 所以我需要把星期天的2号,然后第二周的3,2,1,1,2号放到轮值桌上

总共7天: 第1周=星期日 第2周=周一、周二、周三、周四、周五、周六

 ROTA table
+------+-----+-----+-----+-----+-----+-----+-----+
| WEEK | MON | TUE | WED | THU | FRI | SAT | SUN |
+------+-----+-----+-----+-----+-----+-----+-----+
|    1 |   2 |   2 |   2 |   2 |   2 |   2 |   2 |
|    2 |   3 |   2 |   1 |   1 |   1 |   2 |   1 |
|    3 |   1 |   2 |   1 |   1 |   1 |   1 |   1 |
|    4 |   1 |   1 |   1 |   1 |   2 |   1 |   1 |
|    5 |   1 |   1 |   2 |   1 |   1 |   1 |   1 |
+------+-----+-----+-----+-----+-----+-----+-----+
上述数字存储在移位表中。因此,对于我的7天,这7天的总小时数为2,3,2,1,1,2=51.5小时

SHIFTS Table
+-------+-------+
| SHIFT | HOURS |
+-------+-------+
|     1 | 8.5   |
|     2 | 6     |
|     3 | 8     |
+-------+-------+
我正在做一个WHILE循环来获取所需的周和专栏。所以对于上面的例子,我只需要ROTA表中的SUN列。下一个循环将给我周一到周六

起初我试图把这两行合并在一起,然后我可以做一些计数。所以有3次移位2,1次移位3和3次移位1。然后,我可以得到总小时数,但不知道如何做到这一点

当我的查询完成时,我将得到以下两行:

LOOP 1:
+-----+
| SUN |
+-----+
|   2 |
+-----+

LOOP 2:
+-----+-----+-----+-----+-----+-----+
| MON | TUE | WED | THU | FRI | SAT |
+-----+-----+-----+-----+-----+-----+
|   3 |   2 |   1 |   1 |   1 |   2 |
+-----+-----+-----+-----+-----+-----+
我已经将我的查询向后剥离了一点,但其要点如下:

WHILE @cnt <= @totalDays
BEGIN

IF @dayOfWeek = 1 SET @columnList = 'SUN' ELSE 
IF @tempTotalDays >= 7 SET @columnList = 'MON, TUE, WED, THU, FRI, SAT, SUN' ELSE
IF @tempTotalDays = 6  SET @columnList = 'MON, TUE, WED, THU, FRI, SAT' ELSE
IF @tempTotalDays = 5  SET @columnList = 'MON, TUE, WED, THU, FRI' ELSE
IF @tempTotalDays = 4  SET @columnList = 'MON, TUE, WED, THU' ELSE
IF @tempTotalDays = 3  SET @columnList = 'MON, TUE, WED' ELSE
IF @tempTotalDays = 2  SET @columnList = 'MON, TUE' ELSE
IF @tempTotalDays = 1  SET @columnList = 'MON'

SET @sqlCommand = 'select '+ @columnList +' from dbo.ROTA
where WEEK = @rotaWeek'

EXEC sp_executesql @sqlCommand, N'@rotaWeek nvarchar(75), @rotaWeek = @rotaWeek

END;
GO

正如你所看到的,我就快到了。我只是不知道如何计算我的结果,如何从轮班表中选择时间。RoTA表对于我们人类来说是非常可读的,但对于DBMS来说,它不知道一个星期的星期日是下个星期的星期一,或者我们认为表中的值与Mun-Touth-Tou-FRI坐在太阳下的值相邻。 您可以将表格转换为机器可读的形式,第一周的天数为1,2,3,4,5,6,7,第二周的天数为8,9,10,11,12,13,14,等等。计算天数的公式为:day_number=day_of_week+7*week-1

查询:

with days as
(
  select 1 + (7 * (week - 1)) as daynum, mon as shift from rota
  union all
  select 2 + (7 * (week - 1)) as daynum, tue as shift from rota
  union all
  select 3 + (7 * (week - 1)) as daynum, wed as shift from rota
  union all
  select 4 + (7 * (week - 1)) as daynum, thu as shift from rota
  union all
  select 5 + (7 * (week - 1)) as daynum, fri as shift from rota
  union all
  select 6 + (7 * (week - 1)) as daynum, sat as shift from rota
  union all
  select 7 + (7 * (week - 1)) as daynum, sun as shift from rota
)
select sum(s.hours)
from days d
join shifts s on s.shift = d.shift
where d.daynum between @dayOfWeek + (7 * (@rotaWeek - 1))
                   and @dayOfWeek + (7 * (@rotaWeek - 1)) + @totalDays - 1;
当然,如果您更改了数据模型以匹配我的即席日视图,那么查询将减少到上述查询的最后五行

更新:

在请求评论中,您表示希望继续第5周和第1周。您可以使用模运算从第35天到下一天的第1天。\u daynum=daynum%35+1。但这样一来,这就变成了一个迭代过程,每周轮班制甚至可以在计算中使用不止一次。迭代是通过SQL中的递归查询完成的:

with days as
(
  select 1 + (7 * (week - 1)) as daynum, mon as shift from rota
  union all
  select 2 + (7 * (week - 1)) as daynum, tue as shift from rota
  union all
  select 3 + (7 * (week - 1)) as daynum, wed as shift from rota
  union all
  select 4 + (7 * (week - 1)) as daynum, thu as shift from rota
  union all
  select 5 + (7 * (week - 1)) as daynum, fri as shift from rota
  union all
  select 6 + (7 * (week - 1)) as daynum, sat as shift from rota
  union all
  select 7 + (7 * (week - 1)) as daynum, sun as shift from rota
)
, cte (daynum, remaining, hours) as
(
  select d.daynum, @totalDays - 1, s.hours
  from days d
  join shifts s on s.shift = d.shift
  where d.daynum = @dayOfWeek + (7 * (@rotaWeek - 1))
  union all                     
  select d.daynum, cte.remaining - 1, cast(cte.hours + s.hours as decimal(5,1))
  from cte
  join days d on d.daynum = cte.daynum % 35 + 1
  join shifts s on s.shift = d.shift
  where cte.remaining >= 1
)
select max(hours)
from cte;
不幸的是,SQL Server要求递归CTE中的强制转换与列的确切数据类型匹配


演示:

SQL是一种基于集合的语言。你不需要循环。在最坏的情况下,您可以将所有这些检查转换为回复的QueryTanks的SELECT部分中的单个case子句。如果我只是使用SELECT,当我可能需要多次使用同一周行时,它是如何工作的?什么时候你必须考虑一周多次?你的意思是第5周之后又是第1周,@totalDays可以超过35天吗?是的。可能会有35天以上,第5周后会回到第1周,这对我来说并不清楚。我已经用递归查询更新了我的答案,谢谢。我将尝试将其纳入我最初的查询中,以获取准确的轮班时间。