我有一个场景,客户每周都会下订单(周一到周日)。但是,仓库不会在周六/周日进行订单。我有一个标志告诉我一天是否是工作日(= 1)或不是(= 0)。此外,我每天都有订单。现在,仓库希望在星期一之后看到聚合的周末价值。这是原始选择的摘录(结果是来自事实表的cte-aggregate):
day weekday qty
01.12.2016 1 4551
02.12.2016 1 4283
03.12.2016 0 3925
04.12.2016 0 4918
05.12.2016 1 4905
06.12.2016 1 4831
07.12.2016 1 10920
08.12.2016 1 2603
09.12.2016 1 2578
10.12.2016 0 2314
11.12.2016 0 2932
12.12.2016 1 3491
在5.12上。我想事先让T-SQL进行以下计算:
结果如下:
day weekday qty
01.12.2016 1 4551
02.12.2016 1 4283
03.12.2016 0 0
04.12.2016 0 0
05.12.2016 1 13748
06.12.2016 1 4831
限制:我对该数据库没有写入数据权限,因此无法使用临时表。
答案 0 :(得分:1)
变体1:您可以从agregated subqry创建视图。
select
WorkDay,
sum (qty) SumQty,
sum (case when [weekday] = 1 then qty end) SumQtyOnlyWorkDay,
sum (case when [weekday] = 0 then qty end) SumQtyOnlyFreeDay
from (
select *,
[day] WorkDay
from SrcTable t
where [weekday] = 1
union all
select *,
(select top 1 [day] from @T d where d.[day] > t.[day] and d.[weekday] = 1 order by [day] asc) descendantWorkDay
from SrcTable t
where [weekday] = 0) m
group by WorkDay
解决方案只能获得免费日的下一个工作日。它可能像一个qry:
变体2:
select *,
isnull((
select top 1 [day]
from SrcTable d
where d.[day] > t.[day]
and d.[weekday] = 1
and t.[weekday] = 0
order by [day] asc), [day]) descendantWorkDay
from SrcTable t
索引在[日]字段。
在没有必要时尝试避免CTE - 制作最优化qry很复杂(例如,在第一个语句中使用排名函数强制执行计划,而下一个qry不能从索引中受益)。 CTE通常用于递归或全表连接或复杂视图。
答案 1 :(得分:0)
假设您的sql server版本是2012或更高版本,您可以使用此两步流程。
注意:此解决方案最多连续2天,day
列标记为0
。如果0
长周末,它将无法长时间工作。
首先,创建并填充样本表(请在将来的问题中保存此步骤)
DECLARE @T AS TABLE
(
day date,
weekday bit,
qty int
)
INSERT INTO @T VALUES
('01.12.2016', 1, 4551),
('02.12.2016', 1, 4283),
('03.12.2016', 0, 3925),
('04.12.2016', 0, 4918),
('05.12.2016', 1, 4905),
('06.12.2016', 1, 4831),
('07.12.2016', 1, 10920),
('08.12.2016', 1, 2603),
('09.12.2016', 1, 2578),
('10.12.2016', 0, 2314),
('11.12.2016', 0, 2932),
('12.12.2016', 1, 3491)
然后使用common table expression与case
和lag
的几个custom Auth Provider来计算数量。第一个将创建周末第二天的计算数量,第二个将创建一周第一天的计算数量。
;WITH CTE1 AS
(
SELECT day,
weekday,
qty,
CASE WHEN weekday = 0 AND LAG(weekday) OVER (ORDER BY day) = 0 THEN
qty + LAG(qty) OVER (ORDER BY day)
ELSE
qty
END As calculated_qty
FROM @T
), CTE2 AS
(
SELECT day,
weekday,
qty,
CASE WHEN weekday = 1 AND LAG(weekday) OVER (ORDER BY day) = 0 THEN
calculated_qty + LAG(calculated_qty) OVER (ORDER BY day)
ELSE
CASE WHEN weekday = 0 THEN 0 ELSE qty END
END As calculated_qty
FROM CTE1
)
SELECT *
FROM CTE2
结果:
day weekday qty calculated_qty
12.01.2016 00:00:00 True 4551 4551
12.02.2016 00:00:00 True 4283 4283
12.03.2016 00:00:00 False 3925 0
12.04.2016 00:00:00 False 4918 0
12.05.2016 00:00:00 True 4905 13748
12.06.2016 00:00:00 True 4831 4831
12.07.2016 00:00:00 True 10920 10920
12.08.2016 00:00:00 True 2603 2603
12.09.2016 00:00:00 True 2578 2578
12.10.2016 00:00:00 False 2314 0
12.11.2016 00:00:00 False 2932 0
12.12.2016 00:00:00 True 3491 8737
答案 2 :(得分:0)
由于您已被授予使用临时表的权限。这适用于任何数量的非工作日。它遍历表并使用if语句将[false]天放到下一个[true]天 我用Zohar发布的表创建语句。 (这是我的第一篇帖子,所以我希望我能正确发布这个帖子)
DECLARE @T AS TABLE
(
xday date,
xweekday bit,
qty int
)
DECLARE @result AS TABLE -- table to store results
(
xday date,
xweekday bit,
qty int
)
INSERT INTO @T VALUES
('12/01/2016', 1, 4551),
('12/02/2016', 1, 4283),
('12/03/2016', 0, 3925),
('12/04/2016', 0, 4918),
('12/05/2016', 1, 4905),
('12/06/2016', 1, 4831),
('12/07/2016', 1, 10920),
('12/08/2016', 1, 2603),
('12/09/2016', 1, 2578),
('12/10/2016', 0, 2314),
('12/11/2016', 0, 2932),
('12/12/2016', 1, 3491)
declare @xday date
declare @xweekday bit
declare @qty int
declare @sumqty int = 0 -- temp column to hold [false day] qty values
while exists (select * from @T) -- loop through table
begin
select top 1 @xday = xday, @xweekday = xweekday,@qty=qty from @T
order by xday asc
set @sumqty = @sumqty + @qty
if (@xweekday = 1) -- loop though holidays sum qty only
BEGIN
INSERT INTO @result values (@xday,@xweekday,@sumqty)
set @sumqty = 0
END
else
begin
INSERT INTO @result values (@xday,@xweekday,0)
end
delete @T
where xday = @xday
end
select * from @result
should produce this.
xday xweekday qty
2016-12-01 1 4551
2016-12-02 1 4283
2016-12-03 0 0
2016-12-04 0 0
2016-12-05 1 13748
2016-12-06 1 4831
2016-12-07 1 10920
2016-12-08 1 2603
2016-12-09 1 2578
2016-12-10 0 0
2016-12-11 0 0
2016-12-12 1 8737