我有类似的问题 SQL: selecting rows where column value changed from previous row
ypercube我接受的答案
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 ;
查询本身在测试中工作得很好,并且通过正确的临时表组合,我能够在几乎没有时间的情况下从大量数据中生成每日总和可用性的报告。 当我发现使用我们已经完全放弃的MyISAM引擎的表重新创建表以使用InnoDB时,真正的问题出现了,并注意到查询不再按预期工作。
经过一番抨击后,我发现MyISAM似乎按顺序遍历每一行的列(在更新@statusPre之前选择statusChanged),而InnoDB似乎首先完成所有变量的分配,并且只有在它之后填充它结果行,无论分配是在select或where子句中发生在函数(coalesce,greater etc),子查询还是其他方面。
尝试在没有变量的查询中完成此操作似乎总是以相同的方式结束,子查询需要指数级更多的时间来处理更多的行在集合中,导致一个令人费解的分钟(或小时)长时间等待开始并且结束一个状态的事件,而完成的报告应该包括每日的多个总和。
这种类型的查询是否可以在InnoDB引擎上运行,如果是这样,那么应该怎么做? 或者是唯一可行的选项,用于支持WITH语句的数据库产品?
答案 0 :(得分:0)
卸下
KEY personstate
(PersonID
,StateID
)
解决了这个问题。
不知道为什么,但无论如何都不是真的需要,时间戳键是更重要的一个,可以很好地加快查询速度。