2016-08-08 8 views
1

Ich frage mich, ob es möglich ist, eine einzelne Abfrage auszuführen, die mir folgendes erzählt:
Mysql vergleichen durchschnittliche Ergebnisse mit aktuellen Ergebnis in einer einzigen Abfrage

die Namen aller Anwendungen erhalten, die (derzeit haben

Tabelle 1 Ausführung) Jobs die durchschnittliche historische Laufzeit von mehr als: Auftragsverlauf

  • Job Startzeit
  • Job Endzeit
  • Auftragsstatus (Erfolg, Fehler, Ausführung, etc.)
  • ID-Anwendung, den Job ausgelöst

Tabelle 2: Anwendungen

  • ID
  • Namen

Es schien wie eine einfache Frage zu beantworten, aber eine MySQL-Abfrage erstellen, hat sich als ziemlich verwickelt sein (wenn auch faszinierend) Herausforderung ...

Die Abfrage, um die Arbeitsplätze greifen muss, wo satus = executing, verwenden Sie die application.id für andere Jobs zu suchen, die eine passende haben application.id und status = success, im Durchschnitt der (end_time bis start_time) und vergleichen dann die average time mit dem (current_time-start_time) der aktuell ausgeführten Jobs. Schließlich muss die Anwendungs-ID von allen Jobs, die diesen Test nicht bestehen, die application.name aus der Anwendungstabelle abrufen. Ist das in einer einzigen Abfrage überhaupt möglich?

Für diese Frage angenommen current_time wird als Argument übergeben.

Ich habe versucht, eine dreifach verschachtelte Abfrage, aber ich bekomme den folgenden Fehler, und ich weiß nicht warum. Ich habe ein paar Stunden damit verbracht, diese Arbeit zu bekommen, aber ich bin schon in über meinen Kopf hier:

ERROR 1054 (42S22): Unknown column 'jh.start_time' in 'having clause'

Dies ist mein Versuch:

SELECT name FROM application 
WHERE application.id IN (
    SELECT application_id 
    FROM job_history AS jh 
    WHERE application_id IN (
     SELECT application_id 
     FROM job_history 
     WHERE status='EXECUTION') 
    AND jh.status='SUCCESS' 
    HAVING (avg(jh.end_time - jh.start_time)) < (current_time - jh.start_time) 
    ); 

Edit: Wie vorgeschlagen, hier sind einige Beispieldaten.

Tabelle 1

+--------+------------+------------+----------+----------------+ 
| job_id | status | start_time | end_time | application_id | 
+--------+------------+------------+----------+----------------+ 
| job1 | successful |  100 |  200 | app1   | 
| job2 | failed  |  150 |  350 | app2   | 
| job3 | successful |  200 |  400 | app1   | 
| job4 | execution |  500 |  0 | app1   | 
| job5 | successful |  600 |  800 | app3   | 
+--------+------------+------------+----------+----------------+ 

Tabelle 2

+------+------------------+ 
| id |  name  | 
+------+------------------+ 
| app1 | Team Green's app | 
| app2 | Team Blue's app | 
| app3 | Team Red's app | 
+------+------------------+ 

Ich möchte job4, verwenden Sie die application_id greifenjob1 und job3 zu finden. Dann nehmen Sie die durchschnittliche Laufzeit von job1 und job3 und vergleichen Sie es mit der aktuellen Laufzeit von job4. Wenn die aktuelle Laufzeit größer als die durchschnittliche Laufzeit ist, möchte ich den Anwendungsnamen melden: Team Greens App.

+0

Sie werden vielleicht mehr Erfolg haben, wenn Sie Beispieldaten und die erwarteten Ergebnisse liefern. – sgeddes

Antwort

1

Wenn ich Ihre Frage richtig verstehe, ist hier eine Option mit einer join. Von hier aus ist es einfach, die where Kriterien auf Ihre Bedürfnisse anzupassen:

select distinct a.name 
from applications a 
    join jobhistory jh on a.id = jh.applicationid 
    join (
     select applicationid, avg(endtime - starttime) avgtime 
     from jobhistory 
     where status = 'success' 
     group by applicationid 
    ) t on a.id = t.applicationid 
where jh.status = 'execution' and 
    @current_time - jh.starttime > t.avgtime 
+0

Schön! Ich mag, wohin das geht, aber wird das nicht nur Ergebnisse mit dem Status 'Erfolg' liefern? Oder in diesem Fall eine Empy-Menge, denn später suchen wir nach Status = 'Ausführung'. –

+0

@EthanStrider - pro Kommentar (', die eine übereinstimmende application.id und status = success' haben), das ist es, was die' Join' und die Unterabfrage erreichen. Es gibt die 'avg'-Zeit zurück, so dass Sie sie mit denen vergleichen können, die noch im äußeren Haupt-'Where'-Kriterium ausgeführt werden. Haben Sie das schon versucht, gibt es die falschen Ergebnisse zurück? – sgeddes

+0

Die Jobs, die aktiv ausgeführt werden, werden in der gleichen Tabelle wie die Jobs gespeichert, die beendet wurden. Also muss ich zuerst die aktiven Jobs erfassen und dann die Anwendungs-ID verwenden, um historische Jobs zu identifizieren, die erfolgreich beendet wurden. Dann nehmen Sie die durchschnittliche Zeit der historischen Jobs, um zu beenden, und gehen * zurück * zu den aktiven Jobs und vergleichen Sie die durchschnittliche Laufzeit mit der aktuellen Laufzeit. Ich werde meine Beschreibung oben mit einigen Beispieldaten aktualisieren. –