2016-09-24 2 views
0

Hallo Ich habe die folgenden zwei Tabellen, die ein Dokument mit seiner Bühne und eine History-Tabelle darstellt, welche das Zeitdokument zeigt wurde zur nächsten Stufe bewegtMysql Join-Tabelle auf den neuesten Eintrag, der von Zeit

CREATE TABLE `document` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `description` text, 
    `stage` tinyint(4) NOT NULL DEFAULT '0', 
    `customer_name` varchar(100) DEFAULT NULL, 
    `creator_id` bigint(20) NOT NULL DEFAULT '0', 
    `customer_city` varchar(100) DEFAULT NULL, 
    `customer_state` varchar(100) DEFAULT NULL, 
    `customer_zip` varchar(50) DEFAULT NULL, 
    `customer_contact` varchar(100) DEFAULT NULL, 
    `number` varchar(100) DEFAULT NULL, 
    `latitude` float NOT NULL DEFAULT '0', 
    `longitude` float NOT NULL DEFAULT '0', 
    `creation_date` varchar(50) DEFAULT NULL, 
    `expanded_description` text, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; 

CREATE TABLE IF NOT EXISTS `document_history` (
    `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT, 
    `doc_id` bigint(20) NOT NULL, 
    `modifying_time` datetime DEFAULT NULL, 
    `changed_to_stage` tinyint(3) unsigned DEFAULT NULL, 
    `old_stage` tinyint(3) unsigned DEFAULT NULL, 
    `user_modified` bigint(20) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

Ich brauche zu bekommen Zählstatistik basierend auf dem ausgewählten Zeitraum. Zum Beispiel muss ich wissen, wie viele Dokumente in Phase 1 während des ausgewählten Zeitraums waren, aber das Problem ist, dass wenn ein Dokument während dieses Zeitraums in mehreren verschiedenen Phasen war, ich es nur für den letzten zählen muss Bühne, z wenn doc in Phase war 1 und danach in Stufe 2 - ich brauche es für die Bühne nur zu zählen, 2.

Hier ist, was ich bis jetzt haben:

SELECT 
round(sum(case when dh.modifying_time between '2016-09-15' and '2016-09-24' and dh.changed_to_stage = 1 then 1 else 0 end),0) entry_count, 
round(sum(case when dh.modifying_time between '2016-09-15' and '2016-09-24' and dh.changed_to_stage = 3 then 1 else 0 end),0) pricing_count, 
round(sum(case when dh.modifying_time between '2016-09-15' and '2016-09-24' and dh.changed_to_stage = 5 then 1 else 0 end),0) executed_count, 
round(sum(case when dh.modifying_time between '2016-09-15' and '2016-09-24' and dh.changed_to_stage = 7 then 1 else 0 end),0) approved_count, 
round(sum(case when dh.modifying_time between '2016-09-15' and '2016-09-24' and dh.changed_to_stage = 9 then 1 else 0 end),0) canceled_count 
FROM document doc join document_history dh on doc.id=dh.doc_id 

Das Problem hierbei ist, dass das Dokument zweimal gezählt, wenn es in diesem Zeitraum in zwei verschiedenen Phasen war.

Jede Hilfe wird geschätzt.

Danke und viele Grüße

+0

Bitte fügen Sie Beispieldaten hinzu, um zu reproduzieren. Erzähle uns auch die Regel, Datensätze in die History-Tabelle zu schreiben. Behalten Sie den tatsächlichen Rekord in der Geschichte auch? –

+0

Der Datensatz in der Protokolltabelle wird beim Erstellen eines Dokuments hinzugefügt, auch wenn ein Dokument von einer Phase zur nächsten verschoben wird. –

Antwort

1

Sie wollen einfach nur die letzten Stufe auszuwählen, und dann können Sie die Logik in den where tun. Aber ich würde vorschlagen, das Datum Zustand der WHERE erste und das Loswerden von ROUND() bewegen (für intengers wirklich?):

SELECT sum(case when dh.changed_to_stage = 1 then 1 else 0 end) as entry_count, 
     sum(case when dh.changed_to_stage = 3 then 1 else 0 end) as pricing_count, 
     sum(case when dh.changed_to_stage = 5 then 1 else 0 end) as executed_count, 
     sum(case when dh.changed_to_stage = 7 then 1 else 0 end) as approved_count, 
     sum(case when dh.changed_to_stage = 9 then 1 else 0 end) as canceled_count 
FROM document doc join 
    document_history dh 
    on doc.id = dh.doc_id 
WHERE dh.modifying_time between '2016-09-15' and '2016-09-24' and 
     dh.modifying_time = (SELECT MAX(dh2.modifying_time) 
          FROM document_history dh2 
          WHERE dh2.doc_id = dh.doc_id AND 
           dh2.modifying_time between '2016-09-15' and '2016-09-24' 
         ); 

Hinweise:

  • Lagern Sie keine Datumsangaben als Zeichenfolgen (z als creation_date).
  • Sie sollten between mit Datum oder Datetime verwenden. Dein Ausdruck tut wahrscheinlich nicht, was du vorhast. Schreiben Sie es als dh.modifying_time >= '2016-09-15' and dh.modifying_time < '2016-09-25', was wahrscheinlich ist, was Sie vorhaben.
  • Wenn Sie alle Dokumente behalten möchten, verwenden Sie left join statt inner join und verschieben Sie die where Bedingungen in eine on Klausel.
  • Und round() mit einem ganzzahligen Argument? Ich verstehe das nicht.
  • Und, wie geschrieben, die Abfrage benötigt die document Tabelle überhaupt nicht, nur document_history. Sie könnten from document_history als eine Vereinfachung betrachten.
+0

Alle Daten sind Datum Zeiten, hier ist ein Fehler in dem Beispiel, ich habe einige Spalten entfernt (die Tabelle ist mit 40 Spalten :) Sie sind richtig für die Runde - es ist ein Fehler, ich werde es entfernen. Ich werde Ihre Lösung testen, danke für die Ratschläge –

+0

Ich denke, dass die Bereichsprüfung nur 'dh.modifying_time <'2016-09-25'' sein sollte. Wenn eine Etappe am 14.09. Zuletzt geändert wurde, hat sie in der Zeit vom 15.09. Bis 24.09. Noch die gleiche Etappe. Und die Verknüpfung mit der Tabelle "document" ist wahrscheinlich unnötig. –

+0

@PaulSpiegel. . . Das ist ein guter Punkt. Wie geschrieben, benötigt die Abfrage nicht die Tabelle "join", sondern nur die Tabelle "document_history". –

Verwandte Themen