首先,你的用法GROUP BY不对。随着GROUP BY您将一个组的几行折叠为一个。要获得有意义的结果,您的SELECT子句的所有列都必须包含在子句中,或者必须在其上应用类似orGROUP BY的聚合函数或。否则显示该组的随机行。所以 a总是错的。为确保您做对了,您可以执行(有关更多信息,您可以阅读手册的这一部分)MIN()AVG()SUM()SELECT * FROM foo GROUP BY barSET GLOBAL sql_mode = CONCAT(@@global.sql_mode, ',ONLY_FULL_GROUP_BY');
抱歉 Woton,但您的回答有几个问题。
首先,你的用法
GROUP BY
不对。随着GROUP BY
您将一个组的几行折叠为一个。要获得有意义的结果,您的SELECT
子句的所有列都必须包含在子句中,或者必须在其上应用类似orGROUP BY
的聚合函数或。否则显示该组的随机行。所以 a总是错的。为确保您做对了,您可以执行(有关更多信息,您可以阅读手册的这一部分)MIN()
AVG()
SUM()
SELECT * FROM foo GROUP BY bar
SET GLOBAL sql_mode = CONCAT(@@global.sql_mode, ',ONLY_FULL_GROUP_BY');
您查询的第二个问题是,该
HAVING
子句是对GROUP BY
. 您分组依据的列上的过滤器将在WHERE
子句中。子句中的过滤器HAVING
包括一个聚合函数,例如HAVING SUM(foo) > 5000
.当您不使用聚合函数时,将再次使用随机行。因此,您的
HAVING
子句实际上根本没有过滤任何内容。x
总是大于x - 5
并且x
总是小于x + 5
。例如,适用于您的情况的过滤器(尽管我认为这不是您想要的)将是
HAVING TIMESTAMPDIFF(MINUTE, MIN(horaIfull_oco), MAX(horaIfull_oco)) <= 150
. 这不是你想要的,对吧?如果我理解正确,您想在连续行在某个时间范围内时建立一个组,对吗?为此,我们必须首先生成一个列,稍后我们可以使用它进行分组。
让我们这样做。
这是您的查询,解释如下:
首先要注意的是,在关系数据库中没有行的顺序,除非您指定它。所以我们要在外部查询
ORDER BY
中使用我们想要使用的列GROUP BY
,然后是时间戳/日期时间列。目标是,我们可以使用变量来访问前一行。我们不想在
SET @prev_sinistro := NULL; SET @prev_prefixo := ...
执行主查询之前每次都执行查询,所以我们在一个别名为v
here的子查询中初始化变量。然后,每次
sinistro
orprefixo
或 ordata
与前一行不同,或者horaIfull_oco
当前一行与当前行中该列的值的差异大于 150 分钟时,我们递增@group_number
变量,如果不是我们不这样做(我们只是将变量的当前值分配给变量)。以此类推,我们将当前行的值赋给变量。
@prev_prefixo := sinistro
重要的是,这是在IF()
函数之后完成的。该SELECT
子句按顺序处理。处理下一行时,变量仍保留前一行的值。最后,在外部查询中,我们可以按生成的
gn
列进行分组。编辑:为了满足您的进一步要求,您可以这样做:
编辑2:
所以,我排除
data
并使用了这个查询:关于 id_oco 254 和 277 的问题,当您包括
在
IF()
函数中,这 2 条记录位于不同的组中,如果您不这样做,它们在同一组中,因为它们在 2.5 小时范围内。如果您仍有问题,请同时根据您的样本数据提供所需的结果,以避免进一步混淆。
我做了:
SELECT * FROM table GROUP BY sinistro, prefixo HAVING horaIfull_oco BETWEEN SUBTIME(horaIfull_oco, '02:30:00') and ADDTIME(horaIfull_oco, '02:30:00')