Pregunta

I have a problem similar to SQL: selecting rows where column value changed from previous row

The accepted answer by ypercube which i adapted to

CREATE TABLE `schange` (
    `PersonID` int(11) NOT NULL,
    `StateID` int(11) NOT NULL,
    `TStamp` datetime NOT NULL,
    KEY `tstamp` (`TStamp`),
    KEY `personstate` (`PersonID`, `StateID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


 CREATE TABLE `states` (
    `StateID` int(11) NOT NULL AUTO_INCREMENT,
    `State` varchar(100) NOT NULL,
    `Available` tinyint(1) NOT NULL,
    `Otherstatuseshere` tinyint(1) NOT NULL,
    PRIMARY KEY (`StateID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


SELECT 
    COALESCE((@statusPre <> s.Available), 1) AS statusChanged, 
    c.PersonID, 
    c.TStamp, 
    s.*, 
    @statusPre := s.Available  
FROM schange c 
INNER JOIN states s USING (StateID), 
(SELECT @statusPre:=NULL) AS d 
WHERE PersonID = 1 AND TStamp > "2012-01-01" AND TStamp < "2013-01-01"
ORDER BY TStamp ;

The query itself worked just fine in testing, and with the right mix of temporary tables i was able to generate reports with daily sum availability from a huge pile of data in virtually no time at all. The real problem comes in when i discovered that the tables where using the MyISAM engine, which we have completely abandoned, recreated the tables to use InnoDB, and noticed the query no longer works as expected.

After some bashing head into wall i have discovered that MyISAM seems to go over the columns each row in order (selecting statusChanged before updating @statusPre), while InnoDB seems to do all the variable assigning first, and only after that it populates result rows, regardless if the assigning happens in the select or where clauses, in functions (coalesce, greater etc), subqueries or otherwise.

Trying to accomplish this in a query without variables seems to always end the same way, a subquery requiring exponentially more time to process the more rows are in the set, resulting in a excrushiating minutes (or hours) long wait to get beginning and ending events for one status, while a finished report should include daily sums of multiple.

Can this type of query work on the InnoDB engine, and if so, how should one go about it? or is the only feasible option to go for a database product that supports WITH statements?

¿Fue útil?

Solución

Removing KEY personstate (PersonID, StateID) fixes the problem. No idea why tho, but it was not really required anyway, the timestamp key is the more important one and speeds up the query nicely.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top