2010-11-26 4 views
1

단어 넣는 것은 상당히 어색한 일이지만 항목이 처음에는 관세/고객으로 전환 할 때 행을 원합니다. 품목이 고객으로 전환하는 경우 관세 차이와 상관없이 전환 일자를 반환해야합니다. 품목이 프로젝트를 전환하는 경우 새 프로젝트의 관세가 기존 관세와 동일하지 않은 경우 반환 된 날짜가 변경되어서는 안됩니다.필드가 처음 현재 값으로 변경된 날짜 가져 오기

내가 어떻게 명확하게 할 수 있는지 잘 모르겠지만 제안을 할 수 있습니다.

내 쿼리는 다음과 같습니다

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 

잘못된 날짜

SET @id=2에게 있습니다

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

나에게주는 나에게 제공합니다

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

ㅁ을 떨어져 날로부터, 또한 올바른

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

을 : ICH 나에게 준다 떨어져 날짜

SET @id=3에서, 올바른 것입니다.

다음은 데이터베이스에게의

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

나는 그것이 당신이 찾고있는 결과를 제공한다고 생각합니다.

내부 서브 쿼리 중 하나 인 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

질문이 업데이트되었습니다.문제를 일으키는 데이터는 한 고객/관세에서 변경된 항목이며 다시 다시 항목입니다. –

관련 문제