Frage

Vereinfachte Tabellenstruktur:

CREATE TABLE IF NOT EXISTS `hpa` (
  `id` bigint(15) NOT NULL auto_increment,
  `core` varchar(50) NOT NULL,
  `hostname` varchar(50) NOT NULL,
  `status` varchar(255) NOT NULL,
  `entered_date` int(11) NOT NULL,
  `active_date` int(11) NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `hostname` (`hostname`),
  KEY `status` (`status`),
  KEY `entered_date` (`entered_date`),
  KEY `core` (`core`),
  KEY `active_date` (`active_date`)
)

Dazu habe ich die folgende SQL-Abfrage haben, die einfach alle Datensätze mit den definierten Status summiert werden.

SELECT core,COUNT(hostname) AS hostname_count, MAX(active_date) AS last_active
          FROM `hpa`
          WHERE 
          status != 'OK' AND status != 'Repaired'
          GROUP BY core
          ORDER BY core

Diese Abfrage wurde vereinfacht die innere Joins an unabhängige Daten und zusätzliche Spalten zu entfernen, die die Frage nicht beeinflussen sollte.

MAX (active_date) die gleiche ist für alle Datensätze eines bestimmten Tages und sollte die letzten Tage immer wählen, oder erlauben eine von NOW-Offset (). (Es ist ein Unix-Zeit-Feld)

Ich mag sowohl die Anzahl der: (! Status = 'OK' und Status = 'Repariert')

und die inverse ... Zählung: (status = 'OK' OR Status = 'Repariert')

und die erste Antwort von den zweiten geteilt, für ‚percentage_dead‘ (wahrscheinlich genauso schnell in der Nachbearbeitung zu tun)

für den letzten Tag oder ein Offset (- 86400 für gestern, etc ..)

Tabelle enthält ca. 500k Aufzeichnungen und wächst um etwa 5000 pro Tag so eine einzelne SQL-Abfrage, Looping im Gegensatz wirklich schön wäre ..

ich einige kreative vorstellen, wenn dies tun könnte. Know-how Sie wird geschätzt.

EDIT: Ich bin eine andere SQL-Abfrage für entweder heutige Daten oder Daten von einem Offset mit

.

EDIT: Abfrage funktioniert, ist schnell genug, aber ich kann momentan nicht die Benutzer sortiert auf der Prozentsatz Spalte lassen (die sich von schlechten und guten zählt). Dies ist keine Show Stopper, aber ich erlaube sie sonst auf alles zu sortieren. Die ORDER BY dieses:

SELECT h1.core, MAX(h1.entered_date) AS last_active, 
SUM(CASE WHEN h1.status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS good_host_count,  
SUM(CASE WHEN h1.status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS bad_host_count 
FROM `hpa` h1 
LEFT OUTER JOIN `hpa` h2 ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date) 
WHERE h2.hostname IS NULL 
GROUP BY h1.core 
ORDER BY ( bad_host_count / ( bad_host_count + good_host_count ) ) DESC,h1.core

Gibt mir:     # 1247 - Reference 'bad_host_count' wird nicht unterstützt (Verweis auf die Gruppenfunktion)

EDIT: Gelöst für einen anderen Abschnitt. Folgende Arbeiten und ermöglicht es mir ORDER BY percentage_dead

SELECT c.core, c.last_active, 
SUM(CASE WHEN d.dead = 1 THEN 0 ELSE 1 END) AS good_host_count,  
SUM(CASE WHEN d.dead = 1 THEN 1 ELSE 0 END) AS bad_host_count,
( SUM(CASE WHEN d.dead = 1 THEN 1 ELSE 0 END) * 100/
( (SUM(CASE WHEN d.dead = 1 THEN 0 ELSE 1 END) )+(SUM(CASE WHEN d.dead = 1 THEN 1 ELSE 0 END) ) ) ) AS percentage_dead
FROM `agent_cores` c 
LEFT JOIN `dead_agents` d ON c.core = d.core
WHERE d.active = 1
GROUP BY c.core
ORDER BY percentage_dead
War es hilfreich?

Lösung

Wenn ich verstehe, wollen Sie eine Zählung des Status OK vs. nicht OK Host-Namen zu erhalten, auf dem Datum der letzten Aktivität. Richtig? Und dann sollte die von Kern gruppiert werden.

SELECT core, MAX(active_date)
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS OK_host_count,
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS broken_host_count
FROM `hpa` h1 LEFT OUTER JOIN `hpa` h2 
  ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date)
WHERE h2.hostname IS NULL
GROUP BY core
ORDER BY core;

Dies ist eine Variation des „größte-n-per-Gruppe“ Problems, dass ich eine Menge in SQL Fragen auf Stackoverflow zu sehen.

Zuerst möchte nur die Zeilen wählen, die die neueste Aktivität Datum pro Host-Namen haben, die wir, indem Sie eine äußere Verknüpfung für Zeilen mit demselben Hostnamen und einem größeren active_date tun können. Wo wir keine solche Übereinstimmung zu finden, haben wir bereits die neuesten Zeilen für jeden gegebenen Hostnamen.

Dann Gruppe von Kernen und zählen Sie die Zeilen, die von Status.

Das ist die Lösung für die heutige Datum (keine Zeile unter der Annahme hat eine active_date in der Zukunft). Um vor dem Ergebnis Reihe N Tagen zu beschränken, müssen Sie beiden Tabellen beschränken.

SELECT core, MAX(active_date)
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS OK_host_count,
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS broken_host_count
FROM `hpa` h1 LEFT OUTER JOIN `hpa` h2 
  ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date
  AND h2.active_date <= CURDATE() - INTERVAL 1 DAY)
WHERE h1.active_date <= CURDATE() - INTERVAL 1 DAY AND h2.hostname IS NULL
GROUP BY core
ORDER BY core; 

das Verhältnis zwischen OK und gebrochenem Host-Namen betrifft, so würde ich empfehlen, nur, dass Code in PHP zu berechnen. SQL ermöglicht es Ihnen nicht Spaltenaliasnamen in anderer Auswahlliste Ausdrücke zu verweisen, so dass Sie die oben als eine Unterabfrage wickeln würden und das ist komplexer, als es in diesem Fall wert ist.


Ich habe vergessen, Sie sagen, Sie einen UNIX-Zeitstempel verwenden. Tun Sie etwas wie folgt aus:

SELECT core, MAX(active_date)
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 1 ELSE 0 END) AS OK_host_count,
  SUM(CASE WHEN status IN ('OK', 'Repaired') THEN 0 ELSE 1 END) AS broken_host_count
FROM `hpa` h1 LEFT OUTER JOIN `hpa` h2 
  ON (h1.hostname = h2.hostname AND h1.active_date < h2.active_date
  AND h2.active_date <= UNIX_TIMESTAMP() - 86400)
WHERE h1.active_date <= UNIX_TIMESTAMP() - 86400 AND h2.hostname IS NULL
GROUP BY core
ORDER BY core; 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top