在SQL Server 2018中,我有三个表:
T1 (idService, dateStart, dateStop)
T2 (idService, totalCostOfService)
T3 (idService, companyName)
使用连接,我创建了一个视图:
V1 (idService, dateStart, dateStop, totalCostOfService, companyName)
我们没事。我可以在视图上进行选择并获取已完成的服务列表。
我现在要做的是复制视图的每一行n次,其中n = dateStart-dateStop;每一行都应该有一个“new”totalCostOfService = totalCostOfService / n。
我可以使用临时表,声明变量,使用一些while等等插入临时表等。让我们称之为“程序”
但我想了解的是:
是否有可能直接使用V1上的选择?如果没有,是否可以将“程序”保存为视图,以便我可以轻松选择它?
很抱歉,如果我的问题看起来有些愚蠢,但我对SQL完全不满意。我试着在这里和谷歌搜索,但我找不到我的问题的答案。
谢谢!
您可以使用Tally表而不是rCTE(RBAR):
WITH N AS (
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL)) N(N)),
Tally AS(
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1
CROSS JOIN N N2 --100
CROSS JOIN N N3 --1000
CROSS JOIN N N4) --10000
SELECT *
FROM YourTable
JOIN Tally T ON T.I <= dateStart-dateStop --Assumes dateStart and DateStop are integer values, even though their name implies otherwise
--If they are dates, then use DATEDIFF(DAY, dateStart, dateEnd)
这个数字将产生高达10000的数字(超过27年的数值。这应该远远不够)。
我将假设存在一个numbers
表,其中包含各个值数字的val
列。如果你不这样做,你会发现很多搜索。
在您的视图的FROM
子句的末尾添加此内容:
cross apply (select datediff(day,T1.dateStart,T1.dateStop)+1 as n_days)q1 -- number of days INCLUDING start
cross apply (select dateadd(day,T1.dateStart,n.val) as day_of_charge)q2 from numbers n where n.val between 0 and n_days-1)
然后你就可以在你的SELECT
上拥有以下字段:
T2.totalCostOfService/n_days as totalCostOfService
我很快就会添加一个数字表解决方案。
您可以使用递归CTE:
with cte as (
select idService, dateStart, dateStop,
totalCostOfService / (datediff(day, datestop, datestart) + 1) as dailyCostOfService,
companyName
from v1
union all
select idService,
dateadd(day, 1, dateStart),
dateStop,
dailyCostOfService
companyName
from cte
)
select idservice, dateStart as dateOfService,
dailyCostOfService, companyName
from cte;
请注意,如果任何行超过100天,则需要添加OPTION (MAXRECURSION 0)
。