SQL Server 2008:复制一行n次,其中n是字段中的值

问题描述 投票:0回答:3

在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完全不满意。我试着在这里和谷歌搜索,但我找不到我的问题的答案。

谢谢!

sql sql-server sql-view
3个回答
1
投票

您可以使用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年的数值。这应该远远不够)。


0
投票

我将假设存在一个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

我很快就会添加一个数字表解决方案。


0
投票

您可以使用递归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)

© www.soinside.com 2019 - 2024. All rights reserved.