2011-01-10 1 views
0

Ich habe eine Tabelle namens TaskLog, die die Ergebnisse der verschiedenen geplanten Aufgaben enthält. Es hat (für die Zwecke dieser Frage) diese Säulen:SQL-Abfrage Hilfe - top N-Werte von T.a gruppiert von T.b, T. c

  • TaskLogID: eindeutige ID für diesen Datensatz
  • TaskId: ID der Aufgabe, die
  • Host-Name lautete: Name des Rechners, auf dem es lief
  • RunDate: Datum und Uhrzeit, an dem die Aufgabe
  • Output ausgeführt wurde: Ausgang dieses Versuchs

um die Ausgabe aus dem aktuellen Lauf jedes ta zu bekommen sk, ich hatte mehrere Anfragen wurde die Ausführung, bis ich diese einzelne Abfrage, die viel schneller ist ausgearbeitet:

SELECT TaskLog.TaskID, TaskLog.HostName, TaskLog.Output 
FROM TaskLog 
INNER JOIN (
    SELECT TaskLogID, TaskID, HostName, MAX(RunDate) 
    FROM TaskLog 
    GROUP BY TaskID, HostName 
) AS Latest 
USING (TaskLogID) 

Jetzt würde ich die Ausgabe von jedem der letzten N läuft jeder Aufgabe erhalten möchte, für einige feste N, anstatt nur den letzten Lauf. Gibt es eine Möglichkeit, dies in einer einzigen Abfrage zu tun?

TIA

Antwort

0

Ungeprüfte wie ich MySQL auf diesem System nicht installiert haben (based on here)

select TaskLogID, 
     TaskID, 
     HostName, 
     RunDate 
from (select TaskLogID, 
       TaskID, 
       HostName, 
       RunDate, 
       @num := if(@group = concat(TaskID, HostName), @num + 1, 1) as row_number, 
       @group := concat(TaskID, HostName) as dummy 
     from TaskLog) as x 
where row_number <= 5; 
+0

Danke, habe ich etwas ähnliches nach dem Lesen der Webseite, die Sie unten verlinkt. –

0

Dies ist, wo MySQL Mangel an Fensterfunktionen wie Row_Number() wirklich weh tut.

Select T.TaskLogId, T.TaskId, T.HostName, T.RunDate 
From TaskLog As T 
    Join (
      Select T1.TaskLogId 
       , (Select Count(*) 
        From TaskLog as T2 
        Where T2.TaskId = T1.TaskId 
         And T2.RunDate < T1.RunDate) + 1 As Rnk 
      From TaskLog As T1 
      ) As RankedTasks 
     On RankedTasks.TaskLogId = T.TaskLogId 
      And RankedTasks.Rnk <= <somevalue> 
Order By T.TaskId, T.RunDate 

ADDITION

Unter der Annahme, dass TaskLogId eine Autoinkrement Spalte ist, könnten Sie so etwas wie die folgenden können (in diesem Beispiel nahm ich an, Ihnen die Top 5 Produkte angefordert):

Select T.TaskLogId, T.TaskId, T.HostName, T.RunDate 
From TaskLog As T 
    Join (
      Select Tasks1.TaskId 
       , (
        Select T4.TaskLogId 
        From TaskLog As T4 
        Where T4.TaskId = Tasks.TaskId 
        Order By T4.RunDate Desc 
        Limit 5, 1 
        ) As UpperTaskLogId 
      From (
        Select T3.TaskId 
        From TaskLog As T3 
        Group By T3.TaskId 
        ) As Tasks1 
      ) As LastId 
     On LastId.TaskId = T.TaskId 
      And LastId.UpperTaskLogId >= T.TaskLogId 
+0

Das sieht aus wie es sollte funktionieren, aber ich habe es aufgegeben zu warten, bis es fertig ist. :-(Ich suche nach einer einzigen Abfrage, die schneller als mehrere Abfragen ist. –

+0

@Ben Slusky - Versprach nie, es würde schnell laufen :). Ich habe eine andere Lösung geschrieben, die möglicherweise schneller läuft, die die LIMIT-Anweisung in MySQL verwendet. – Thomas

+0

@Ben Slusky - Nm. Ich glaube nicht, dass MySQL Limit in einer Unterabfrage richtig einhält. – Thomas