2015-04-02 19 views
5

Tutaj mam przykładowe dane studentów mających RollNumbers i ich kody kursu.Wiersz po wierszu (bez kursora lub pętli)

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

Wynik powinien być Coursecode a ich data egzaminu

np (uporządkować Wyraźne Coursecodes)

pierwsze jestem zbieranie CS201 i przypisanie tej coursecode datę; umieszczenie go w tabeli tymczasowej, a następnie wybrałem CS101 i sprawdzenie w tabeli tymczasowej, czy numery RollNumber tego kodu Course pasują do innych numerów RollLiczba innych kodów kursu w tabeli tymczasowej.

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

mój kod:

  • #temp3 zawiera wszystkie dane (CourseCodes, RollNumbers)
  • #mytemp1 (dane wyjściowe)

i Kursor zawiera odrębny 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 

Ten kod działa poprawnie, ale przy zbyt wiele czasu (4110222 Records)

Każda pomoc będzie mile widziane

+0

Możemy użyć CTE, aby zrobić to skutecznie. przygotuje dla ciebie przykład – ughai

+0

Pozwól nam [kontynuować tę dyskusję na czacie] (http://chat.stackoverflow.com/rooms/74330/discussion-between-kanwar-kakkar-and-ughai). – superB

Odpowiedz

3

Oto kod. Wierzę, że masz błąd w produkcji i CS101 powinno poprzedzać 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 

wyjściowy:

Code Date 
CS101 1 
CS201 2 
ME102 1 
PT101 3 

EDIT:

cte1 powróci:

code rn 
CS101 1 
CS201 2 
ME102 3 
PT101 4 

główne prace odbywa się w cte2. Jest to rekurencyjne wspólne wyrażenie tabelowe. Najpierw trzeba wziąć top 1 wiersz z cte1:

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

Następnie postępuje rekurencji:

Jesteś łączącą cte1 na cte2 i wybrać następujące RNS (2, 3 ...) i sprawdzić, czy są jakieś rolki w CS201 pasujących do bułek w poprzednich kodów (CS101) w pierwszej kolejności należy sprawdzić, czy istnieją jakieś rolki w ME102 pasujących do bułek w poprzednich kodów (CS101, CS201) w drugim etapie itd. Jeśli istnieje jeszcze wrócisz 1 0:

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

Ostatnia cte3 wykonuje następujące czynności: jeśli Data = 0, to zwróć 1, w przeciwnym razie zwróć sumę dat w poprzednich wierszach, w tym bieżący wiersz.

Edit1:

Ponieważ moje rozumienie jest błędne tutaj jest jeszcze jedna wypowiedź:

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  

wyjściowa:

Code Date 
CS101 1 
CS201 2 
ME102 1 
PT101 2 

EDIT2:

To jest szalone, ale tutaj jest kod, który wydaje się działać:

Powiązane problemy