2015-04-02 19 views
5

Hier habe ich Beispieldaten von Studenten mit RollNumbers und ihre Kurscodes.Zeile für Zeile (ohne Cursor oder Schleifen)

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

Ergebnis sollte Coursecode und ihre Prüfungstermin sein

beispiels (aussortieren Distinct Coursecodes)

Zuerst habe ich CS201 bin Kommissionierung und Zuweisen dass coursecode ein Datum; Wenn ich es in eine temporäre Tabelle platziere, dann wählte ich CS101 und checkt in der temporären Tabelle ein, ob die RollNumbers dieses Coursecodes mit einer anderen RollNumber eines anderen Coursecodes in der temporären Tabelle übereinstimmen.

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

Mein Code:

  • #temp3 enthält alle Daten (CourseCodes, RollNumbers)
  • #mytemp1 (Ausgangsdaten)

und Cursor enthält die Distinct 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 

Dieser Code funktioniert gut, aber zu viel Zeit (4.110.222 Datensätze)

Jede Hilfe

+0

Wir können CTE verwenden, um dies effizient zu tun. wird ein Beispiel für dich erarbeiten – ughai

+0

Lass uns [diese Diskussion im Chat fortsetzen] (http://chat.stackoverflow.com/rooms/74330/discussion-between-kanwar-kakkar-and-ughai). – superB

Antwort

3

Hier geschätzt nehmen würde, ist ein Code. Ich glaube, dass Sie Fehler in der Ausgabe haben und CS101CS201 vorausgehen sollte:

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 

Ausgang:

Code Date 
CS101 1 
CS201 2 
ME102 1 
PT101 3 

EDIT:

cte1 zurückkehren wird:

code rn 
CS101 1 
CS201 2 
ME102 3 
PT101 4 

Die Hauptarbeit ist in cte2 getan. Es ist rekursiver allgemeiner Tabellenausdruck. Zuerst nehmen Sie Top-1 Reihe von cte1:

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

Dann wird die Rekursion fortschreitet:

Du cte1 auf cte2 Füge- und wählen folgende rns (2, 3, ...) und prüfen, ob es welche gibt in CS201 Walzen, die Rollen in früheren Codes (CS101) in der ersten Stufe entsprechen, zu überprüfen, ob es irgendwelche Rollen in ME102, die Rollen in früheren Codes (CS101, CS201) in der zweiten Stufe entsprechen usw. wenn vorhanden du 1 sonst 0:

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

Letzte cte3 tut das folgende: wenn Datum = 0 dann geben Sie 1 zurück, sonst geben Sie die Summe der Daten in vorherigen Zeilen einschließlich der aktuellen Zeile zurück.

EDIT1:

Da mein Verständnis falsch war hier ist eine weitere Aussage:

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  

Ausgang:

Code Date 
CS101 1 
CS201 2 
ME102 1 
PT101 2 

EDIT2:

Das ist verrückt, aber hier ist Code, der zu funktionieren scheint:

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