Bra*_*rad 15 mysql sql group-by datetime-generation
假设我有一个包含3列的表:
我有以下记录:
1, 2010-01-01 15:00:00, Some Title
2, 2010-01-01 15:00:02, Some Title
3, 2010-01-02 15:00:00, Some Title
Run Code Online (Sandbox Code Playgroud)
我需要做一个彼此在3秒内的GROUP BY记录.对于此表,第1行和第2行将组合在一起.
这里有一个类似的问题: Mysql DateTime组15分钟
我也发现了这个:http: //www.artfulsoftware.com/infotree/queries.php#106
我不知道如何将这些方法转换为可以工作几秒钟的方法.在SO问题上方法的问题在于,在我看来它只适用于落在从已知点开始的时间仓内的记录.例如,如果我FLOOR()
以秒为单位工作,间隔为5秒,则15:00:04的时间将与15:00:01分组,但不会与15:00:06分组.
这有意义吗?如果需要进一步说明,请与我们联系.
编辑:对于一组数字,{1,2,3,4,5,6,7,50,51,60},似乎最好将它们分组{1,2,3,4,5, 6,7},{50,51},{60},以便每个分组行取决于行是否在前一个3秒内.我知道这会改变一些事情,对不起,我很抱歉.
我试图模糊匹配来自不同服务器的日志.服务器#1可以记录项目"项目#1",服务器#2将在服务器#1的几秒内记录相同的项目"项目#1".我需要在两个日志行上做一些聚合函数.不幸的是,由于服务器软件的性质,我只有标题可以继续.
Chr*_*ham 15
我正在使用Tom H.的优秀想法,但在这里做的有点不同:
我们可以找到作为链的起点的所有时间,而不是找到作为链的开头的所有行,然后返回并且ifnd匹配时间的行.
这里的查询#1应该告诉您哪些时间是链的开头,通过查找哪些时间在它们之下没有任何时间但在3秒内:
SELECT DISTINCT Timestamp
FROM Table a
LEFT JOIN Table b
ON (b.Timestamp >= a.TimeStamp - INTERVAL 3 SECONDS
AND b.Timestamp < a.Timestamp)
WHERE b.Timestamp IS NULL
Run Code Online (Sandbox Code Playgroud)
然后对于每一行,我们可以找到最小的链起始时间戳,该时间戳小于查询#2的时间戳:
SELECT Table.id, MAX(StartOfChains.TimeStamp) AS ChainStartTime
FROM Table
JOIN ([query #1]) StartofChains
ON Table.Timestamp >= StartOfChains.TimeStamp
GROUP BY Table.id
Run Code Online (Sandbox Code Playgroud)
一旦我们拥有了它,我们可以根据需要GROUP BY它.
SELECT COUNT(*) --or whatever
FROM Table
JOIN ([query #2]) GroupingQuery
ON Table.id = GroupingQuery.id
GROUP BY GroupingQuery.ChainStartTime
Run Code Online (Sandbox Code Playgroud)
我不完全确定这与Tom H的答案分开是否足够明显,但听起来好像你在实施方面遇到了麻烦,而我正在思考它,所以我想我会再次发帖.祝好运!
现在我认为我理解你的问题,基于你对OMG Ponies的评论回应,我认为我有一个基于集合的解决方案.我们的想法是首先根据标题找到任何链的起点.链的开头将被定义为在该行之前三秒内没有匹配的任何行:
SELECT
MT1.my_id,
MT1.title,
MT1.my_time
FROM
My_Table MT1
LEFT OUTER JOIN My_Table MT2 ON
MT2.title = MT1.title AND
(
MT2.my_time < MT1.my_time OR
(MT2.my_time = MT1.my_time AND MT2.my_id < MT1.my_id)
) AND
MT2.my_time >= MT1.my_time - INTERVAL 3 SECONDS
WHERE
MT2.my_id IS NULL
Run Code Online (Sandbox Code Playgroud)
现在我们可以假设任何非链起动器都属于它们之前出现的链起动器.由于MySQL不支持CTE,您可能希望将上述结果抛出到临时表中,因为这样可以节省下面相同子查询的多个连接.
SELECT
SQ1.my_id,
COUNT(*) -- You didn't say what you were trying to calculate, just that you needed to group them
FROM
(
SELECT
MT1.my_id,
MT1.title,
MT1.my_time
FROM
My_Table MT1
LEFT OUTER JOIN My_Table MT2 ON
MT2.title = MT1.title AND
(
MT2.my_time < MT1.my_time OR
(MT2.my_time = MT1.my_time AND MT2.my_id < MT1.my_id)
) AND
MT2.my_time >= MT1.my_time - INTERVAL 3 SECONDS
WHERE
MT2.my_id IS NULL
) SQ1
INNER JOIN My_Table MT3 ON
MT3.title = SQ1.title AND
MT3.my_time >= SQ1.my_time
LEFT OUTER JOIN
(
SELECT
MT1.my_id,
MT1.title,
MT1.my_time
FROM
My_Table MT1
LEFT OUTER JOIN My_Table MT2 ON
MT2.title = MT1.title AND
(
MT2.my_time < MT1.my_time OR
(MT2.my_time = MT1.my_time AND MT2.my_id < MT1.my_id)
) AND
MT2.my_time >= MT1.my_time - INTERVAL 3 SECONDS
WHERE
MT2.my_id IS NULL
) SQ2 ON
SQ2.title = SQ1.title AND
SQ2.my_time > SQ1.my_time AND
SQ2.my_time <= MT3.my_time
WHERE
SQ2.my_id IS NULL
Run Code Online (Sandbox Code Playgroud)
如果您可以使用CTE或使用临时表,这看起来会简单得多.使用临时表也可能有助于提高性能.
此外,如果您可以准确匹配时间戳,则会出现此问题.如果是这种情况,那么您需要稍微调整查询以使用id和时间戳的组合来区分具有匹配时间戳值的行.
编辑:更改查询以按时间戳处理完全匹配.