CTE循环查询

时间:2013-04-09 08:56:09

标签: sql loops with-statement

首先,我会向你解释情况。

我想将数据从一个表(View_Solidnet_Training)传输到另一个表(OBJ_Availability)。 有一个问题:在视图中有一个Start-和EndDate!在OBJ_Availability中,每个日期都有一条记录。因此视图中的一行在另一个表中有多行。

我必须与CTE合作。所以光标对我来说是没有选择的。 中间WITH运行完美,但当我想添加额外WITH以检查ID是否不为零时,它必须更改变量@Start和{{ 1}}到视图中的新记录。

对不起我的英语,这不是那么好,但我希望你了解情况。

这是我的代码:

@End

这样的东西,但我不明白它从何处获取视图的信息。我从来没有在任何地方提到这个名字?

1 个答案:

答案 0 :(得分:0)

我还不能发表评论,所以在回答之前我需要问几个问题。

1,为什么CTE的名称与视图的名称相同?它永远不会起作用。

2,你的意思是'检查ID是否不为零,它必须将变量@Start和@End更改为视图中的新记录',我无法弄清楚为什么你需要这样做空检查

3,您确定可以使用DateValue + 1来获取下一个日期吗?你应该使用DATEADD吗?

最后,你不能在CTE中使用CTE,这是行不通的。在CTE中声明变量也不可能。

这是我最好的客人:

首先,正如您所提到的,您的视图有一个startdate列和一个enddate列,

所以我假设视图中有StartDate和EndDate列,这是我的sql:

DECLARE @start AS DATETIME
DECLARE @end AS DATETIME

SELECT @start = min(StartDate)
from View_Solidnet_Training 
where PK_Training_ID is not null

SELECT @end = max(EndDate) 
from View_Solidnet_Training 
where PK_Training_ID is not null

;with cte_dates as
(
    select @start DateValue
    union all
    select DateValue + 1
    from cte_dates
    where DateValue + 1 <= cast(@end as datetime)
)
into OBJ_Availability  
select v.PK_Training_ID, DateValue, 'AM', 2, 'Test' --columns from the view
from cte_dates cte
join View_Solidnet_Training v on v.StartDate < cte.DateValue and cte.DateValue < v.EndDate 
where v.PK_Training_ID is not null

max()和min函数计算出视图中最新和最旧的日期

然后CTE cte_dates创建一个从@start到@end的日期列表

然后加入CTE将在StartDate到EndDate

的范围内重复记录

希望这个帮助

顺便说一下,我的家用电脑上没有sql,所以我可以检查一下

SELECT @start = min(StartDate)
from View_Solidnet_Training 
where PK_Training_ID is not null

是否运行,但你应该明白

使用while而不是CTE:

DECLARE @start AS DATETIME
DECLARE @end AS DATETIME

SELECT @start = min(StartDate)
from View_Solidnet_Training 
where PK_Training_ID is not null

SELECT @end = max(EndDate) 
from View_Solidnet_Training 
where PK_Training_ID is not null

DECLARE @AllDates table
        (DateValue datetime)

DECLARE @dCounter datetime
SELECT @dCounter = @start

WHILE @dCounter <= @end
BEGIN
 INSERT INTO @AllDates VALUES (@dCounter)
 SELECT @dCounter=@dCounter+1 
END

insert into OBJ_Availability  
select v.PK_Training_ID, DateValue, 'AM', 2, 'Test' --columns from the view
from @AllDates d
join View_Solidnet_Training v on v.StartDate < d.DateValue and d.DateValue < v.EndDate 
where v.PK_Training_ID is not null

或者您甚至可以

DECLARE @start AS DATETIME
DECLARE @end AS DATETIME

SELECT @start = min(StartDate)
from View_Solidnet_Training 
where PK_Training_ID is not null

SELECT @end = max(EndDate) 
from View_Solidnet_Training 
where PK_Training_ID is not null


DECLARE @dCounter datetime
SELECT @dCounter = @start

WHILE @dCounter <= @end
BEGIN

    insert into OBJ_Availability  
    select v.PK_Training_ID, DateValue, 'AM', 2, 'Test' --columns from the view
    from View_Solidnet_Training v
    where v on v.StartDate < @dCounter and @dCounter < v.EndDate and v.PK_Training_ID is not null

    SELECT @dCounter=@dCounter+1 
END