2010-11-26 5 views
1

これは言葉にするのはかなり面倒なことですが、アイテムが最初に関税/顧客に切り替えられたときにその行が必要です。 品目が顧客を切り替える場合、関税の違いにかかわらず、スイッチの日付を返す必要があります。品目がプロジェクトを切り替える場合、新しいプロジェクトの関税が古いものと同じでない限り、返された日付は変更してはなりません。フィールドが最初に現在の値に変更された日付を取得する

どのように私はそれをより明確にすることができますか分かりませんが、私は提案に開放されています。

私のクエリは次のようになります。

SET @id=2間違った日付である私に

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

を与える

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 

は私を与える:

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

WhをICHが正しいか、離れた日から

SET @id=3は私を与える:

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

離れた日から、また正しいいます。ここで

は、データベース

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'); 

編集です:アイテムは、古い関税や顧客に戻って行くことができます。この場合、表示される日付は、これが発生した日付でなければなりません。

答えて

1

私の以前の回答は、新しいデータセットでも動作するように見えましたが、私はあなたが見ている問題を理解していると思います。新しい提案されたソリューション:

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

あなたが探している結果が得られると思います。

内部サブクエリの1つであるi_date_pair_infoが、各日付と明示的に後のすべてのの変更がある場合は、と明示的にペアになっています。グループ化することで、最も早い変更を除くすべてが削除されます。

+0

残念ながら、私はこれを実際のデータで動作させることはできません。それは同じシナリオのテストデータで動作するので、誰も何も投稿しなければ、終わりに恩恵をあげます。 –

+0

Bummer。新しいテストデータを投稿できる場合は、別のテストデータを取る時間があります。ありがとう。 – Riedsio

+0

は何もできませんでしたが、これは明らかに履歴データが必要なので、これは別のテーブルではるかに良いでしょう。しかし、試してくれてありがとう。 –

2

興味深い状況です。ここで私はもちろん

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 

思い付いたものだあなたが合うように、あなたはいくつかのWHERE ItemID = @idに挿入することができます。内側のクエリが多いほど良いでしょう。いずれにしても

、それはとても

+--------+-----------+----------+------------+---------------------+ 
| 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 | 
+--------+-----------+----------+------------+---------------------+ 

になり、既存のデータセットで動作するように表示されます。 Lemmeは、それがうまくいかないテストデータを提供できるかどうかを知っています。

+1

+1これはテストデータでは間違いなく機能しますが、実際のデータに問題があるようです。パターンを特定すると、さらにテストデータを追加しますが、それは来週まで待たなければなりません。 –

+0

質問が更新されました。問題の原因となるデータは、1つの顧客/関税から変更された商品、その後に戻ってくる商品です。 –

関連する問題