2016-03-26 10 views
0

Kleine Erklärung:ROWNUMBER Funktion in Oracle

Ich habe eine Tabelle passes genannt und es wird mit 2 Tischen (services (cod_serv) und atend (Pass)) verknüpft. Pässe können für verschiedene Dienste dupliziert werden.

Eg .: Wenn ich 3-Dienste haben, kann ich drei Pässe nº 01, ABER nicht 2 Pässe nº 1 für den gleichen Dienst (I definiert es in meinem Composite Primärschlüssel).

Für Tests habe ich 102 Durchgänge hinzugefügt (alle mit Situation = "F" und mit demselben Datum (heute)). Dann fügte ich Pässe für jeden Dienst hinzu (ich habe 3 Dienste).

Die folgende Abfrage soll zeigen, wie die schema mehr oder weniger definiert ist.

SELECT DISTINCT s.pass, s.data, cod_serv, situation, hour, min 
FROM passes 
JOIN atend a ON s.pass = a.pass; 

PASS  DATA  COD_SERV  S  HOUR   MIN 
-----  -------- ---------  -  -------  ------- 
04   26/03/16 2    F  12    24 
04   26/03/16 1    F  13    27 
13   26/03/16 1    F  14    26 
18   26/03/16 3    F  14    27 
18   26/03/16 2    F  14    28 
15   26/03/16 1    F  14    29 
10   26/03/16 3    F  14    30 
...  ...  ...   ... ...   ... 

Dann mag ich den 100. (ROWNUMBER()) Pass erhalten (wie es zeigt, darunter 21 ist) ab einem bestimmten Zeitpunkt mit der Situation = ‚F‘ Bestellung per Stunde und min.

Zeilennummer 100:

21   26/03/16 3    F  14    34 

Die folgende query wird nichts zurückkehrt, und ich kann nicht herausfinden, warum. Übrigens habe ich mehr als 100 Pässe mit dieser Situation.

SELECT DISTINCT pass, data, cod_serv, situation FROM 
    (SELECT DISTINCT a.pass, s.data, cod_serv, situation, 
      ROW_NUMBER() OVER(PARTITION BY situation, hour, min 
          ORDER BY situation, hour, min) row 
    FROM passes s 
    JOIN atend a ON s.pass = a.pass 
    WHERE situation = 'F' AND 
     TRUNC(a.data) = TRUNC('some date')) 
WHERE row = 100; 

EDIT:

Meine Anfrage zur Zeit:

SELECT DISTINCT pass, cod_serv FROM 
    (SELECT DISTINCT s.pass, cod_serv, 
      ROW_NUMBER() OVER(PARTITION BY TRUNC(s.data) 
          ORDER BY a.hour, a.min) row 
    FROM passes s 
    JOIN atend a ON s.pass = a.pass 
    WHERE s.situation = 'F' AND 
     TRUNC(s.data) = TRUNC(SYSDATE)) 
WHERE row = 100; 
+0

Sie wollen '(Partition nach Datenreihenfolge nach Stunde, min)' –

+0

und 'Situation'? – developer033

+0

Alle Zeilen haben sowieso den gleichen Wert für die Situation (wegen 'situacao = 'F''), so dass es nicht notwendig ist, sie in die Fensterdefinition oder in die Reihenfolge von –

Antwort

0

die gleichen Felder in PARTITION BY und ORDER BY in einer OVER Klausel macht wenig Sinn zu haben.

Die PARTITION BY Klausel sollte die Felder aufgelistet, die die Gruppe definieren, in dem Sie Datensätze aus 1.

Die ORDER BY Klausel definiert die Reihenfolge, beginnen zu zählen, in denen Datensätze innerhalb dieser Gruppe gezählt werden.

Wie Sie schreiben:

I want to get the 100th (ROWNUMBER()) pass from a specific date with the situation = 'F' ordering by hour and min

... Sie sagen wirklich in Worte fassen, was in diesen Klauseln gestellt werden muss:

ROW_NUMBER() OVER(PARTITION BY data, situation ORDER BY hour, min) 

Also Ihr Hauptfehler Stunden zu setzen war und min in der PARTITION BY Klausel, so dass die Aufzeichnung von 1 beginnend, sobald eine Minute Unterschied gefunden wurde, geben die meisten Ihrer Aufzeichnungen die Nummer 1.

bearbeiten

Es scheint, dass Oracle die gleiche row Nummer nicht beibehalten, wenn es nicht ausgewählt ist.Dies liegt wahrscheinlich daran, dass die nicht deterministisch ist. Was immer der Grund, es kann gelöst werden, indem die row in der äußeren Abfrage Auswahl:

SELECT pass, row FROM (... etc ...) WHERE row = 100 

Wenn Sie nur den Pass benötigen, können Sie diese Abfrage wickeln wieder:

SELECT pass FROM (
    SELECT pass, row FROM (... etc ...) WHERE row = 100 
) 
+0

Danke für deine Unterstützung, aber leider funktioniert es nicht. Aber ich denke, es funktioniert nicht als erstes, weil, wie ich in meinem letzten Schnitt erwähnt habe, das innere 'select' die Anzahl der Zeilen in der 'pass'-Tabelle sogar mit' DISTINCT' zurückgibt. Also muss ich es zuerst beheben – developer033

+0

Es könnte auch interessant sein, auf die Ausgabe von 'SELECT Daten zu sehen, count (*) FROM Übergänge WHERE Situation = 'F' GROUP BY Daten HAVING count (*)> 99' um zu sehen, wie viele Fälle Du hast mehr als 100 Zeilen. – trincot

+0

Ich habe es getestet. Count = 102 (es ist korrekt, ich habe alle Situationen auf 'F' aktualisiert). – developer033

0

Wie wäre das?

Zuerst vor row_number() tun, alle Ihre Filter anwenden (da Sie nicht die Zeilen zählen wollen, dass Sie gehen, um herauszufiltern):

SELECT s.pass, s.data, cod_serv, s.situation, a.hour, a.min 
FROM passes s 
JOIN atend a ON s.pass = a.pass 
WHERE s.situation = 'F' 
AND TRUNC(s.data) = TRUNC(SYSDATE) 

Nun wickeln, dass in einem äußeren Abfrage, wo Sie row_number() gelten:

SELECT pass, data, cod_serv, situation, hour, min, 
     rowseq=row_number() over (order by hour, min) 
FROM (
    SELECT s.pass, s.data, cod_serv, s.situation, a.hour, a.min 
    FROM passes s 
    JOIN atend a ON s.pass = a.pass 
    WHERE s.situation = 'F' 
    AND TRUNC(s.data) = TRUNC(SYSDATE) 
) t1 

Schließlich wickeln, dass in einer äußeren Abfrage, wo Sie den Filter für die „Hundertstel“ Rekord gelten:

SELECT pass, data, cod_serv, situation, hour, min 
FROM (
    SELECT pass, data, cod_serv, situation, hour, min, 
      rowseq=row_number() over (order by hour, min) 
    FROM (
     SELECT s.pass, s.data, cod_serv, s.situation, a.hour, a.min 
     FROM passes s 
     JOIN atend a ON s.pass = a.pass 
     WHERE s.situation = 'F' 
     AND TRUNC(s.data) = TRUNC(SYSDATE) 
    ) t1 
WHERE rowseq = 100 

Schließlich, wenn Teile angepasst werden müssen (verschiedene Filter, Joins, etc.), können Sie jede dieser Ebenen von inneren Abfragen selbstständig ausführen, um Ihre Zwischenergebnisse zu überprüfen, um sicherzustellen, dass Ihr Ergebnis ist, was Sie wollen .

+0

Vielen Dank für Ihre Antwort, aber es gibt mir einen Fehler: 'ORA-00923: FROM Schlüsselwort nicht gefunden, wo erwartet ' – developer033