2015-04-02 65 views
5

這裏我有學生有RollNumbers和他們的coursecodes的示例數據。按行排(沒有光標或循環)

------------------------- 
    Roll  CourseCode 
-------------------------- 
    1011  CS201 
    2213  CS201 
    3312  CS101 
    4000  CS201 
    1011  CS101 
    5312  ME102 
    1011  PT101 
    3312  ME102 

結果應該是Coursecode和他們的考試日期

e.g(整理出鮮明的Coursecodes)

首先我採摘CS201和分配是coursecode日期;把它放在臨時表中,然後我選擇CS101並檢查臨時表是否該課程代碼的滾動編號與臨時表中的其他課程代碼的任何其他滾動編號相匹配。

--------------------- 
    Code Date 
--------------------- 
    CS101 1 
    CS201 2 
    ME102 1 
    PT101 3 

我的代碼:

  • #temp3包含所有數據(CourseCodes,RollNumbers)
  • #mytemp1(輸出數據)

和光標包含鮮明coursecodes

SET @cursor = CURSOR FOR 
SELECT DISTINCT coursecode 
FROM #temp3 
ORDER BY CourseCode 

OPEN @cursor 
FETCH NEXT 
FROM @cursor INTO @cursorid 


WHILE @@FETCH_STATUS = 0 
    BEGIN 

     BEGIN 
      SET @j=1 
      WHILE(@j !=9999999) 
      BEGIN 

       IF(SELECT COUNT(*) FROM #temp3 WHERE CourseCode = @cursorid AND RegdNo IN (
        SELECT RegdNo FROM #temp3 WHERE CourseCode IN (SELECT coursecode FROM #myTemp1 WHERE counter1 = @j) 
       )) = 0 
         BEGIN 
          INSERT INTO #myTemp1 VALUES (@cursorid,@j) 
          SET @j=9999999 
         END 
       ELSE 
       BEGIN 
         SET @j = @j + 1 
       END 
      END 
    END 

FETCH NEXT 
FROM @cursor INTO @cursorid 
END 
CLOSE @cursor 
DEALLOCATE @cursor 

此代碼工作正常,但服用任何幫助將不勝感激

+0

我們可以使用CTE來有效地做到這一點。將爲您提供一個示例 – ughai 2015-04-02 09:56:43

+0

讓我們[在聊天中繼續討論](http://chat.stackoverflow.com/rooms/74330/discussion-between-kanwar-kakkar-and-ughai)。 – superB 2015-04-02 10:19:26

回答

3

下面是一些代碼太多時間(4110222個記錄)

。我相信,你的輸出有錯誤和CS101應先CS201

DECLARE @t TABLE (Roll INT, Code CHAR(5)) 

INSERT INTO @t 
VALUES (1011, 'CS201'), 
     (2213, 'CS201'), 
     (3312, 'CS101'), 
     (4000, 'CS201'), 
     (1011, 'CS101'), 
     (5312, 'ME102'), 
     (1011, 'PT101'), 
     (3319, 'ME102'); 

WITH cte1 
      AS (SELECT code , 
         ROW_NUMBER() OVER (ORDER BY Code) AS rn 
       FROM  @t 
       GROUP BY code 
      ), 
     cte2 
      AS (SELECT code , 
         rn , 
         1 AS Date 
       FROM  cte1 
       WHERE rn = 1 
       UNION ALL 
       SELECT c1.code , 
         c1.rn , 
         CASE WHEN EXISTS (SELECT * 
              FROM  @t a 
                JOIN @t b ON a.Roll = b.Roll 
                JOIN cte1 c ON c.rn < c1.rn 
                   AND b.Code = c.code 
              WHERE a.code = c1.code) THEN 1 
          ELSE 0 
         END 
       FROM  cte1 c1 
         JOIN cte2 c2 ON c1.rn = c2.rn + 1 
      ), 
     cte3 
      AS (SELECT Code , 
         CASE WHEN Date = 0 THEN 1 
          ELSE SUM(Date) OVER (ORDER BY rn) 
         END AS Date 
       FROM  cte2 
      ) 
    SELECT * FROM cte3 

輸出:

Code Date 
CS101 1 
CS201 2 
ME102 1 
PT101 3 

編輯:

cte1將返回:

code rn 
CS101 1 
CS201 2 
ME102 3 
PT101 4 

主要工作在cte2完成。它是遞歸公用表表達式。 首先,你拿頂端1列從cte1

SELECT code , 
     rn , 
     1 AS Date 
     FROM  cte1 
     WHERE rn = 1 

然後遞歸的進展:

你是加盟的cte2cte1,並挑選以下RNS(2,3 ...),並檢查是否有任何在CS201輥匹配在第一步驟之前的代碼(CS101)輥即,檢查是否存在返回在ME102在第二步驟等,如果存在先前的代碼(CS101, CS201)符合輥的任何軋輥1否則爲0:

code rn Date 
CS101 1 1 
CS201 2 1 
ME102 3 0 
PT101 4 1 

最後cte3執行以下操作:如果Date = 0,則返回1,否則返回包括當前行在內的先前行中的日期總和。

EDIT1:

因爲我的理解是不正確的是這裏多了一個聲明:

WITH cte 
      AS (SELECT code , 
         ROW_NUMBER() OVER (ORDER BY Code) AS rn 
       FROM  @t 
       GROUP BY code 
      ) 

    SELECT co.Code, 
    DENSE_RANK() OVER(ORDER BY ISNULL(o.Code, co.Code)) AS Date 
      FROM cte  co 
    OUTER APPLY(SELECT TOP 1 ci.Code 
       FROM cte ci 
       WHERE ci.rn < co.rn AND 
       NOT EXISTS(SELECT * FROM @t 
         WHERE code = ci.code AND 
         roll IN(SELECT roll FROM @t WHERE code = co.code)) ORDER BY ci.rn) o 
    ORDER BY co.rn  

輸出:

Code Date 
CS101 1 
CS201 2 
ME102 1 
PT101 2 

EDIT2:

這是瘋了,但是,這裏是似乎工作的代碼:

WITH cte 
      AS (SELECT * , 
         ROW_NUMBER() OVER (PARTITION BY roll ORDER BY Code) AS Date 
       FROM  @t 
      ) 
    SELECT Code , 
      MAX(Date) AS Date 
    FROM cte 
    GROUP BY Code