根据每月SQL的天数将行从一个表添加到另一个表

时间:2017-10-08 14:33:42

标签: sql-server

我有一张名为Students的表,有10条学生记录

ID StudentName
1   Student a
2   Student b
-   ------  -
10  Student N

现在我想根据几个月的日子将这10名学生添加到另一张表中,例如

ID StudentName DayOfMonth
1  Student a        1
2  Student a        2
-  ---------        -
-  Student a        31
-  Student b         1
-  ------- b         31

并且所有学生都有任何SQL动态解决方案 我尝试使用Cursor,但如果表中有55名学生,则需要大约2分钟。当我在执行proc期间检查表时,它会在几秒钟内生成 1705行,即(55x31)但是它会因为挂起或其他东西而在2分钟后做出反应它显示了成功消息。 任何帮助将不胜感激。

@fkStudentID int,
@fkClassID int,
@fkSessionID int,
@Dated date,

AS
Declare @Days  as  int
Set @Days = DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,@Dated),0)))
Declare @OffSet as int
DECLARE @MyCursor CURSOR;
DECLARE @MyField int;
BEGIN
SET @MyCursor = CURSOR FOR
select fkStudentID from dbo.tblAdmission
    where fkClassID = @fkClassID and fkSessionID = @fkSessionID 

OPEN @MyCursor 
FETCH NEXT FROM @MyCursor 
   INTO @MyField 

WHILE @@FETCH_STATUS = 0
BEGIN

    While(@OffSet <= @Days)
    Begin

        if(IsNull((Select count(RegisterID) from tblRegister where @MyField = fkStudentID and fkClassID = @fkClassID and fkSessionID = @fkSessionID and [Dayofmonth] = @OffSet),0) = 0)
        Begin
            Insert into tblRegister (fkStudentID, fkClassID, fkSessionID, [DayOfMonth], Dated) values (@MyField, @fkClassID, @fkSessionID, @OffSet, DATEADD(DAY, (@OffSet - 1), DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)))
        End
        Set @OffSet = @OffSet + 1
    End
    Set @OffSet = 1
FETCH NEXT FROM @MyCursor 
  INTO @MyField 

END; 

CLOSE @MyCursor ;
DEALLOCATE @MyCursor;
END;

1 个答案:

答案 0 :(得分:1)

我不确定为什么在proc结束之前会看到延迟,但最好尽可能使用基于集合的查询而不是游标以获得最佳性能。我希望只要你有适当的索引(理想情况下,dbo.tblAdmission fkClassID和fkSessionID列上的唯一聚簇索引以及dbo.tblRegister fkStudentID,fkClassID,fkSessionID和DayOfMonth上的唯一索引),下面的示例将在不到一秒的时间内运行)。

CREATE PROC dbo.Example
    @fkClassID int,
    @fkSessionID int,
    @Dated date
AS

INSERT INTO dbo.tblRegister
    (
      fkStudentID
    , fkClassID
    , fkSessionID
    , DayOfMonth
    , Dated
    ) 
SELECT
      a.fkStudentID
    , a.fkClassID
    , a.fkSessionID
    , o.offset
    , DATEADD(DAY, (o.offset - 1), DATEADD(MONTH, DATEDIFF(MONTH, '', GETDATE()), ''))
FROM dbo.tblAdmission AS a
CROSS JOIN (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10)
                ,(11),(12),(13),(14),(15),(16),(17),(18),(19),(20)
                ,(21),(22),(23),(24),(25),(26),(27),(28),(29),(30),(31)) AS o(offset)
WHERE
    a.fkClassID =  @fkClassID 
    AND a.fkSessionID = @fkSessionID
    AND o.offset <= DAY(DATEADD(DD,-1,DATEADD(MM,DATEDIFF(MM,-1,@Dated),0)))
    AND NOT EXISTS(
        SELECT 1
        FROM dbo.tblRegister AS r
        WHERE
            r.fkStudentID = a.fkStudentID 
            AND r.fkClassID = a.fkClassID
            AND r.fkSessionID = a.fkSessionID
            AND [Dayofmonth] = o.offset
        );