Mehrfaches SELECT TOP (5)

Holger69

Neuer Benutzer
Beiträge
2
Guten Tag Zusammen,

ich betreibe eine Labordatenbank, welche die Messergebnisse von Kundenproben verwaltet und über ein Ticketsystem verarbeitet.
Jeder Kunde kann 1:n Prozesse (ProzessID) haben
Jeder Kunde kann 1:n Tickets (TicketID) haben.

Im Laufe der Zeit, schickt ein Kunde mehrere Proben (SampleID) seiner Prozesse.
Immer dann, wenn er eine oder mehrere Proben schickt, entsteht ein Ticket. Das heißt, ein Ticket ist wie ein Container, in dem mehrere Proben zusammengefasst sind.

Ich hoffe, ich habe mich soweit verständlich ausgedrückt.

Jedes Ticket kann also 1:n Proben haben, wobei die jeweiligen SampleID‘s auch die dazugehörige ProzessID als Fremdschlüssel mit sich führen.

Für eine TicketID möchte ich nun die jeweils letzten 5 Proben der im Ticket enthaltenen Prozesse ermitteln.
Mit „WHERE ProzessID IN (SELECT ProzessID FROM tblSample WHERE TicketID = @TicketID)“ als Kriterium, kann ich die über die im Ticket enthaltenen Prozesse ermitteln.

Gäbe es in einem Ticket stets nur eine Probe - also auch nur ein Prozess -, so würde
SELECT TOP (5) SampleID FROM tblSample … + WHERE-Kriterium, wie oben formuliert,
das richtige Ergebnis liefern.

Da es aber im Ticket mehrere Proben/Prozesse gibt bzw. geben kann, müsste dieser SELECT TOP (5)-Befehl nacheinander für jede ProzessID ausgeführt werden, die durch die Unterabfrage „SELECT ProzessID from tblSample WHERE TicketID = @TicketID“ geliefert werden.

Wie macht man das?
Muss man hier wirklich iterieren (und wenn ja, wie?) oder gibt es einen anderen Weg?

Vielen Dank im Voraus an alle, die sich damit beschäftigen möchten.
Gruß,

Holger
 
Werbung:
Mmh, mir fehlt da irgendwie ein Top Kriterium.
Die 5 schlimmsten Proben?
Die 5 ältesten?
Jüngsten?
Seltensten?

Die Vermutung, dass es um die jüngsten geht, ist naheliegend, aber unklar.
Im Normalfall hat man dafür eine Datums / Zeit Spalte.

Für solche und die allermeisten anderen SQL Fragen postet man am besten die Table Create Statements und eine Handvoll Beispieldaten.
 
Hallo,

Vielen Dank für den Hinweis.
Das TOP-Kriterium habe ich bereits beschrieben, nämlich SELECT TOP(5) SampleID FROM tblSample ...
Die vorhandene Datumspalte (SampleDate) ginge natürlich auch, ist aber für meine Fragestellung unerheblich.

Es geht letztlich nur darum, dass mehrere SELECT TOP (5) ausgeführt werden müssen
Die Tabelle ist einfach aufgebaut und alle notwendigen Schlüssel sind enthalten

PK SampleID, int
FK Process ID int,
FK TicketID int,

Der Rest sind Felder, die für die Fragestellung unerheblich sind.

Ich habe eine Tabelle mit Beispieldaten angehängt.
Jede SampleID ist einer ProcessID und einer TicketID zugeordnet. Die Farben sind auf die ProzessID bezogen.
Der Kunde schickt insgesamt 25 Proben von seinen 3 Prozessen. Dies Proben werden in 9 Ticktes zusammengefasst. Er schickt immer alle drei Prozesse AUSSER bei Ticket Nr. 5, da hat er nur den Prozess Nr. 2 geschickt. (Siehe "!")

Farblich markiert sind jeweils die letzten 5 SampleID's eines Prozesses, ausgehend von Ticket Nr. 9
Wegen der "fehlenden" Proben bei Ticket Nr. 5 gibt es diesen kleinen Versatz.

Das von mir benötigte Abfrageergebnis soll am Ende alle farbigen SampleID's liefern (10 - 25 OHNE 11), also jeweils die letzten 5 eines Prozesses. Gezählt wird abwärts von der vorgegebenen Ticketnummer (hier Nr. 9), welche als Variable der Abfrage mitgegeben wird.

Ich hoffe, ich konnte es nun etwas deutlicher beschreiben.
 

Anhänge

Gut, das hat mir etwas weiter geholfen.

Das TOP-Kriterium habe ich bereits beschrieben
Naja, ich kann damit nichts anfangen. Bin aber auch kein MS SQL Fachmann.
Wenn top das macht, was hier steht, braucht man ein ORDER BY, sonst gibt es beliebige (5 in deinem Fall) Datensätze aus. Das kann man wollen oder auch nicht. Manchmal kann es auch das sein, was man wirklich braucht.

Es geht letztlich nur darum, dass mehrere SELECT TOP (5) ausgeführt werden müssen
Von solchen Ideen oder solchen
Muss man hier wirklich iterieren (und wenn ja, wie?)
musst Du Dich bei SQL lösen. RDBMS != Excel oder Algorithmus. DB arbeiten Mengen-orientiert und in SQL gibt es keine Iteration.
Wenn Du meinst, hier oder beim nächsten Problem, Du müsstest iterieren, dann denk noch mal drüber nach. Programmierbare DB können natürlich iterieren, aber das will man nicht, weil es langsam ist und der Code das System meist komplizierter macht als nötig.

Außerdem ist es so, das ein technisches Schlüsselfeld niemals zur Erzielung einer Funktionalität verwendet werden soll.
Die vorhandene Datumspalte (SampleDate) ginge natürlich auch, ist aber für meine Fragestellung unerheblich.
Diese Datumsspalten wären m.E. die erste (und einzige) Wahl für ein Top .. Order By und auch andere Lösungswege. Primär oder Fremdschlüssel nimmt man dafür nicht.

Top ist letztlich für Dein Problem nicht geeignet, denke ich, weil es einfach nur Datensätze zählt und nicht Inhalte berücksichtigt (nicht kann).
Ich habe es also mit Window Functions versucht:
Code:
  with wdw as
      (select processid, sampleid,
              row_number() over (partition by processid order by sampleid desc) rn#
         from tblsample)
select processid, sampleid
  from wdw
 where rn# <= 5
 order by processid, sampleid desc;
[code]

Wie Du das Ergebnis auf bestimmte Tickets einschränkst und ob Du die sample_id (mit process_id) mehrfach ausgeben willst oder nur das netto Ergebnis aller eindeutigen Samples musst Du Dir überlegen. Ist mir zumindest anhand Deiner Frage und des PDF nicht  klar gewesen.

Apropos PDF:
Wer hindert Dich daran, ein Create Table Statement mit ein paar Inserts Statements zu posten? Das würde allen Beteiligten helfen / Arbeit abnehmen. Ich zumindest bin nicht so ein Master Brain Bug, dass ich sowas zuverlässig per Kopfrechnen schaffe.
 
Richtig, TOP ohne ORDER BY ist zumindest in der Theorie zufällig in der Ausgabe. Praktisch kommt i.d.R. das selbe Ergebnis zurück, solange sich an der Tabelle nichts ändert. Darauf darf man sich aber nicht verlassen.

Der Ansatz mit ROW_NUMBER() währe auch meine Wahl, PARTITION BY processid ORDER BY datum DESC. Damit entsteht dann ein Ranking und in einem äußeren Select Filterst du dann auf die niedrigsten fünf Datensätze.
 
Werbung:
Praktisch kommt i.d.R. das selbe Ergebnis zurück, solange sich an der Tabelle nichts ändert.
Zitat aus der Doku:

Enable synchronized sequential scans

This allows sequential scans of large tables to synchronize with each other, so that concurrent scans read the same block at about the same time and hence share the I/O workload. When this is enabled, a scan might start in the middle of the table and then wrap around the end to cover all rows, so as to synchronize with the activity of scans already in progress. This can result in unpredictable changes in the row ordering returned by queries that have no ORDER BY clause.


Das heißt, daß 2 User die Resultate in unterschiedlicher Reihenfolge bekommen können, selbst wenn sich NICHTS an der Tabelle ändert.
 
Zurück
Oben