2010-11-26 13 views
1

Es ist eine ziemlich peinliche Sache, in Worte zu fassen, aber ich möchte die Zeile, wenn der Artikel zuerst zu einem Tarif/Kunden wechselte. Wenn ein Artikel den Kunden wechselt, sollte das Datum des Switch zurückgegeben werden, unabhängig von der Tarifdifferenz. Wenn ein Artikel zwischen Projekten wechselt, darf sich das zurückgegebene Datum nicht ändern, es sei denn, der Tarif des neuen Projekts ist nicht derselbe wie der alte.Erhalte das Datum, an dem ein Feld zum ersten Mal geändert wurde

Nicht ganz sicher, wie ich es klarer machen kann, aber ich bin offen für Vorschläge.

Meine Frage wie folgt aussieht:

SET @id = 1; 
SELECT DISTINCT 
    ip.ItemID, 
    ip.ProjectID, 
    p.TariffID, 
    p.CustomerID, 
    cs.Date 
FROM item_project ip 
LEFT JOIN item_project ip1 
    ON ip.ItemID = ip1.ItemID 
    AND ip.Date < ip1.Date 
LEFT JOIN project p 
    ON ip.ProjectID = p.ProjectID 
LEFT JOIN (
    SELECT 
     ip.ItemID, 
     ip.Date 
    FROM item_project ip 
    LEFT JOIN item_project ip1 
     ON ip.ProjectID = ip1.ProjectID 
     AND ip.Date > ip1.Date 
    LEFT JOIN project p 
     ON ip.ProjectID = p.ProjectID 
    WHERE ip.ItemID = @id 
     AND ip1.ItemID IS NULL 
     AND p.CustomerID = (
      SELECT p.CustomerID 
      FROM project p 
      LEFT JOIN item_project ip 
       ON p.ProjectID = ip.ProjectID 
      LEFT JOIN item_project ip1 
       ON ip.ItemID = ip1.ItemID 
       AND ip.Date < ip1.Date 
      WHERE ip.ItemID = @id 
       AND ip1.ItemID IS NULL 
      ) 
     AND p.TariffID = (
      SELECT p.TariffID 
      FROM project p 
      LEFT JOIN item_project ip 
       ON p.ProjectID = ip.ProjectID 
      LEFT JOIN item_project ip1 
       ON ip.ItemID = ip1.ItemID 
       AND ip.Date < ip1.Date 
      WHERE ip.ItemID = @id 
       AND ip1.ItemID IS NULL 
      ) 
) AS cs 
    ON ip.ItemID = cs.ItemID 
WHERE ip.ItemID = @id 
    AND ip1.ItemID IS NULL 

, die mir gibt

"ItemID","ProjectID","TariffID","CustomerID","Date" 
"1","2","1","1","2010-11-10 00:00:00" 

, die das falsche Datum

SET @id=2 gibt mir ist:

"2","2","1","1",NULL 

Wh ich richtig ist, abgesehen von dem Datum

SET @id=3 gibt mir:

"3","2","1","1",NULL 

die auch richtig ist, abgesehen von dem Tag.

Hier ist die Datenbank

CREATE TABLE IF NOT EXISTS `item_project` (
    `ID` int(10) unsigned NOT NULL auto_increment, 
    `ItemID` varchar(10) NOT NULL, 
    `ProjectID` int(10) unsigned NOT NULL, 
    `Date` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP, 
    PRIMARY KEY (`ID`) 
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1; 

INSERT INTO `item_project` (`ID`, `ItemID`, `ProjectID`, `Date`) VALUES 
    (1, '1', 1, '2010-11-05 00:00:00'), 
    (2, '1', 2, '2010-11-10 00:00:00'), 
    (3, '1', 3, '2010-11-20 00:00:00'), 
    (4, '2', 2, '2010-11-21 00:00:00'), 
    (5, '3', 4, '2010-11-21 00:00:00'), 
    (6, '3', 2, '2010-11-22 00:00:00'), 
    (7, '1', 2, '2010-11-23 00:00:00'), 

CREATE TABLE IF NOT EXISTS `project` (
    `ProjectID` int(10) unsigned NOT NULL auto_increment, 
    `Name` varchar(45) NOT NULL, 
    `TariffID` varchar(45) NOT NULL, 
    `CustomerID` varchar(45) NOT NULL, 
    PRIMARY KEY (`ProjectID`) 
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1; 

INSERT INTO `project` (`ProjectID`, `Name`, `TariffID`, `CustomerID`) VALUES 
    (1, 'Test', '2', '1'), 
    (2, 'Another test', '1', '1'), 
    (3, 'Project1', '1', '1'), 
    (4, 'Main project', '2', '2'); 

CREATE TABLE IF NOT EXISTS `tariff` (
    `TariffID` int(10) unsigned NOT NULL auto_increment, 
    `Tariff` varchar(45) NOT NULL, 
    PRIMARY KEY (`TariffID`) 
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1; 

INSERT INTO `tariff` (`TariffID`, `Tariff`) VALUES 
    (1, 'Tariff 1'), 
    (2, 'Tariff 2'); 

bearbeiten: Ein Element kann zu einem alten Tarif oder Kunden zurückgehen. In diesem Fall sollte das angezeigte Datum das Datum sein, an dem dies geschah.

Antwort

1

Meine vorherige Antwort schien auch mit dem neuen Datensatz zu funktionieren, aber ich glaube, ich verstehe das Problem, das Sie sehen. Neue vorgeschlagene Lösung:

SELECT i_general.ItemID, ProjectID, TariffID, CustomerID, the_date 
FROM 
(
    SELECT ip.ItemID, p.ProjectID, p.TariffID, p.CustomerID 
    FROM item_project ip 
    INNER JOIN project p ON ip.ProjectID = p.ProjectID 
    INNER JOIN tariff t ON p.TariffID = t.TariffID 
    INNER JOIN (
     SELECT ip.ItemID, MAX(Date) AS max_date 
     FROM item_project ip 
     GROUP BY ip.ItemID 
    ) ip_max ON ip_max.ItemID=ip.ItemID AND ip_max.max_date=ip.Date 
) i_general 
INNER JOIN 
(
    SELECT ItemID_1 AS ItemID, IF(MAX(Next_Change_Date) IS NULL, MIN(Date_1), MAX(Next_Change_Date)) AS the_date 
    FROM 
    (
     SELECT ItemID_1, Date_1, MIN(Date_2) AS Next_Change_Date 
     FROM 
     (
      SELECT ip1.ItemID AS ItemID_1, ip1.Date AS Date_1, p1.TariffID AS TariffID_1, p1.CustomerID AS CustomerID_1 
      FROM item_project ip1 
      INNER JOIN project p1 ON ip1.ProjectID = p1.ProjectID 
     ) ipp1 
     LEFT JOIN 
     (
      SELECT ip2.ItemID AS ItemID_2, ip2.Date AS Date_2, p2.TariffID AS TariffID_2, p2.CustomerID AS CustomerID_2 
      FROM item_project ip2 
      INNER JOIN project p2 ON ip2.ProjectID = p2.ProjectID 
     ) ipp2 ON ItemID_1=ItemID_2 AND Date_1 < Date_2 AND ((TariffID_1!=TariffID_2 OR CustomerID_1!=CustomerID_2) AND Date_2 IS NOT NULL) 
     GROUP BY ItemID_1, Date_1 
    ) i_date_pair_info 
    GROUP BY ItemID 
) i_date_info ON i_date_info.ItemID = i_general.ItemID

Ich denke, es bietet das Ergebnis, das Sie suchen.

Es ist robuster, in dem eine der inneren Unterabfragen, i_date_pair_info, explizit jedes Datum mit allen nachfolgenden Änderungen, wenn es eins gibt. Die Gruppierung beseitigt dann alle außer der kürzesten Änderung.

+0

Leider kann ich nicht scheinen, dass dies mit den echten Daten funktioniert. Es funktioniert mit den Testdaten im selben Szenario, also gebe ich dir das Kopfgeld am Ende des Tages, wenn niemand sonst etwas posten kann. –

+0

Bumm. Wenn Sie neue Testdaten posten können, habe ich wahrscheinlich noch Zeit, einen weiteren Lauf zu starten. Vielen Dank. – Riedsio

+0

konnte nicht funktionieren, aber es stellt sich heraus, dass dies in einer separaten Tabelle viel besser wäre, da wir jetzt anscheinend auch historische Daten benötigen. Danke fürs ausprobieren. –

2

Interessante Situation. Hier ist, was ich kam mit

SELECT i_general.ItemID, ProjectID, TariffID, CustomerID, the_date 
FROM 
(
    SELECT 
     ip.ItemID, 
     p.ProjectID, 
     p.TariffID, 
     p.CustomerID 
    FROM item_project ip 
    INNER JOIN project p ON ip.ProjectID = p.ProjectID 
    INNER JOIN tariff t ON p.TariffID = t.TariffID 
    INNER JOIN (
     SELECT 
      ip.ItemID, MAX(Date) AS max_date 
     FROM item_project ip 
     GROUP BY ip.ItemID 
     ) ip_max ON ip_max.ItemID=ip.ItemID AND ip_max.max_date=ip.Date 
) i_general 
INNER JOIN (
    SELECT ip1.ItemID, IF(MIN(ip2.Date) IS NULL,MIN(ip1.Date),MIN(ip2.Date)) AS the_date 
    FROM item_project ip1 
    INNER JOIN project p1 ON ip1.ProjectID = p1.ProjectID 
    LEFT JOIN item_project ip2 ON ip1.ItemID=ip2.ItemID AND ip1.Date < ip2.Date 
    LEFT JOIN project p2 ON ip2.ProjectID = p2.ProjectID AND (p2.TariffID!=p1.TariffID OR p2.CustomerID!=p1.CustomerID) 
    GROUP BY ip1.ItemID 
    ) i_date_info ON i_date_info.ItemID = i_general.ItemID 

Natürlich können Sie in ein paar WHERE ItemID = @id einfügen, wie Sie für richtig halten. Je mehr es auf den inneren Fragen gibt, desto besser.

Auf jeden Fall führt es in

+--------+-----------+----------+------------+---------------------+ 
| ItemID | ProjectID | TariffID | CustomerID | the_date   | 
+--------+-----------+----------+------------+---------------------+ 
| 1  |   3 | 1  | 1   | 2010-11-10 00:00:00 | 
| 2  |   2 | 1  | 1   | 2010-11-21 00:00:00 | 
| 3  |   2 | 1  | 1   | 2010-11-22 00:00:00 | 
+--------+-----------+----------+------------+---------------------+ 

So scheint es mit dem vorhandenen Datensatz zu arbeiten. Lemme wissen, ob Sie Testdaten zur Verfügung stellen können, gegen die es nicht funktioniert.

+1

+1 Dies funktioniert definitiv für die Testdaten, aber ich habe Probleme mit den tatsächlichen Daten. Wenn ich ein Muster identifiziere, werde ich weitere Testdaten hinzufügen, aber das muss bis nächste Woche warten. –

+0

Aktualisiert die Frage.Die Daten, die Probleme verursachen, sind die Artikel, die von einem Kunden/Tarif wechseln und dann wieder zurückgehen. –

Verwandte Themen