2016-08-16 5 views
2

Ich habe postgraduate Abschlussdaten von Studenten in meiner Datenbank. Student kann nur einen Abschluss nach dem Abschluss haben, einige Studenten können mehr als einen Abschluss nach Abschluss haben.mehrere Datensätze in einer einzigen Zeile

rollno | pgdegree | score 
-------------------------- 
0001 | 41  | 56 
0002 | 42  | 78 
0002 | 49  | 75 
0003 | 48  | 77 

Hier Roll-Nr. ist mehr als einmal und Roll-Nr. 0001,0003 sind nur einmal.

ich möchte meine gewünschte Ausgabe als:

rollno | pgdegree1 | score1 | pgdegree2 | score2 
------------------------------------------------ 
0001 | 41  | 56  |   | 
0002 | 42  | 78  | 49  | 75 
0003 | 48  | 77  |   | 

Hinweis: in meiner Datenbank jeder Student ein oder zwei Post Abstufung nur haben kann. Nicht mehr als zwei PG-Abschluss.

+0

Wenn Sie genau ein oder zwei PG haben, können Sie die Tabelle mit sich selbst mit dem 'rollno' und Druck' pgdegree' und 'score' für die ursprüngliche und verknüpfte Tabelle verbinden. Contra: Schüler mit nur einem PG haben die gleichen Werte für 'pgdegree1' und' pgdegree2' bzw. 'score1' und' score2'. – Smutje

Antwort

1

Hier ist eine andere Lösung ROW_NUMBER() und bedingte Aggregation mit einigen unnötigen SELECTs sparen:

SELECT s.rollno, 
     MAX(CASE WHEN s.rnk = 1 THEN s.pgdegree END) AS pgdegree1, 
     MAX(CASE WHEN s.rnk = 1 THEN s.score END) AS score1, 
     MAX(CASE WHEN s.rnk = 2 THEN s.pgdegree END) AS pgdegree2, 
     MAX(CASE WHEN s.rnk = 2 THEN s.score END) AS score2 
FROM 
(
    SELECT t.*, 
      ROW_NUMBER() OVER (PARTITION BY t.rollno ORDER BY t.pgdegree, t.score) AS rnk 
    FROM YourTable t 
) s 
GROUP BY s.rollno 
0

Sie eine clevere Pivot-Abfrage verwenden können:

SELECT t.rollno, 
    SUM(CASE WHEN pgdegree = (SELECT MIN(pgdegree) FROM yourTable WHERE rollno = t.rollno) 
      THEN pgdegree ELSE 0 END) AS pgdegree1, 
    SUM(CASE WHEN pgdegree = (SELECT MIN(pgdegree) FROM yourTable WHERE rollno = t.rollno) 
      THEN score ELSE 0 END) AS score1, 
    SUM(CASE WHEN pgdegree = (SELECT MAX(pgdegree) FROM yourTable WHERE rollno = t.rollno) 
      THEN pgdegree ELSE 0 END) AS pgdegree2, 
    SUM(CASE WHEN pgdegree = (SELECT MAX(pgdegree) FROM yourTable WHERE rollno = t.rollno) 
      THEN score ELSE 0 END) AS score2 
FROM yourTable t 
GROUP BY t.rollno 

Erläuterung:

Die ersten beiden CASE Aussagen haben Subqueries die pgdegree wenn dieser Wert gerade ist das Minimum zurück Wert für das gegebene rollno. Diese pgdegree und score werden als die ersten beiden Spalten angezeigt. In ähnlicher Weise verwenden die letzten beiden CASE-Anweisungen den maximalen-Wert, um die zweiten zwei Spalten zu generieren.

+0

Wenn diese Tabelle groß ist, wäre die Leistung schrecklich .. – sagi

+1

Die größte Universität in den USA hat eine Einschreibung von etwas über 60K Studenten (qv [hier] (https://en.wikipedia.org/wiki/List_of_United_States_university_campuses_by_enrollment)). Multiplizieren Sie dies um höchstens 2 für die 2 Grad. Ich halte 100K nicht für so groß, dass diese Abfrage ein großes Problem darstellen sollte. –

+0

Ich redete nicht über 100K Datensätze :), andere Leute können dies auch sehen und ihre Tabellen könnten anders sein. Dies beantwortet diese Frage und wird wahrscheinlich großartig funktionieren. – sagi

1

ein Selbst Sie LEFT JOIN Sekunden pgdegree hinzufügen für eine rollno falls vorhanden. Führen Sie NOT EXISTS aus, um nur Zeilen mit dem niedrigsten pgdegree als t1.pgdegree zurückzugeben.

select t1.rollno, t1.pgdegree, t1.score, t2.pgdegree, t2.score 
from tablename t1 
    left join tablename t2 
     on t1.rollno = t2.rollno and t1.pgdegree < t2.pgdegree 
where not exists (select * from tablename t3 
        where t1.rollno = t3.rollno 
        and t1.pgdegree > t3.pgdegree) 
+0

Ihre Abfrage gibt kein genaues Ergebnis. Ich habe 4529 verschiedene Rollen Nein in der Tabelle, aber Ihre Abfrage ergibt 4614 Zeilen. Die Antwort, die ich akzeptiert habe, genaue Aufzeichnungen zu geben. –

+0

@DhairyaLakhera, haben Sie vielleicht Rollno/Pgdegree Duplikate? – jarlh

0
select 
    rollno, 
    (array_agg(pgdegree))[1] as pgdegree1, 
    (array_agg(score))[1] as score1, 
    (array_agg(pgdegree))[2] as pgdegree2, 
    (array_agg(score))[2] as score2 
from 
    your_table 
group by 
    rollno; 
Verwandte Themen