所有行上的 MySQL GROUP BY 条件(不是 WHERE 或 HAVING)

标签 mysql group-by

我认为这是一个困难的问题(仅适用于 SQL 铁杆),但提出的问题很简单。 我有一个日志表,以 Unix 时间戳记录用户的连接和断开时间:

USER_ID  |   CONN_TIME   |   DISC_TIME
1        |   1533742332  |   1533744332
2        |   1533744232  |   1533744337
1        |   1533744132  |   1533754332
3        |   1533714332  |   1533744532
3        |   1533744032  |   1533744532

现在,我需要一种方法以 10 分钟间隔对行进行分组,并计算每个间隔内的在线用户数量。我知道如何GROUP BY CONN_TIMEDISC_TIME,但这样我只能得到在十分钟间隔内有多少用户连接或断开连接,而不是如何许多用户在线(CONN_TIME - DISC_TIME)

我当前的SQL语句如下:

SELECT DATE_FORMAT(FROM_UNIXTIME(CONN_TIME), '%Y-%m-%d %H:%i') as date, COUNT(*) as hits
FROM Stats
GROUP BY FLOOR(CONN_TIME / 600)

正如您所看到的,我只能获得点击次数,这对于显示用户的事件来说完全不能令人满意。我想知道他当时是否还在线。

最佳答案

好吧,几个小时后,我想我终于找到了类似于您问题的答案。但是,我还没有对其进行彻底测试,因此我不能保证它功能齐全并且完全符合您的需要,使用风险自负。

Here it is as a fiddle现在对我所做的进行一些解释:

首先,我创建了两个 View ,第一个 View 生成 0 到 16 之间的数字,第二个 View 生成 0 到 256 之间的数字。(您可能可以内联这些 View ,但我没有)。

CREATE OR REPLACE VIEW generator_16
AS SELECT 0 n UNION ALL SELECT 1  UNION ALL SELECT 2  UNION ALL
SELECT 3   UNION ALL SELECT 4  UNION ALL SELECT 5  UNION ALL
SELECT 6   UNION ALL SELECT 7  UNION ALL SELECT 8  UNION ALL
SELECT 9   UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL
SELECT 12  UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL
SELECT 15;

CREATE OR REPLACE VIEW generator_256
AS SELECT ( ( hi.n << 4 ) | lo.n ) AS n
FROM generator_16 lo, generator_16 hi;

好的,现在我们可以生成从最低 CONN_TIME 到最高 DISC_TIME 的时间戳:

SELECT UNIX_TIMESTAMP(DATE_ADD(@start_date, INTERVAL @i MINUTE)) AS result_date
FROM generator_256
CROSS JOIN
  (
     SELECT 
       @i:=-10, 
       @start_date:= FROM_UNIXTIME(FLOOR((SELECT MIN(CONN_TIME) FROM Stats) / 600) * 600)
  ) AS init
WHERE UNIX_TIMESTAMP(DATE_ADD(@start_date, INTERVAL@ i: = @i + 10 MINUTE)) 
  BETWEEN(FLOOR((SELECT MIN(CONN_TIME) FROM Stats) / 600) * 600) 
  AND(CEIL((SELECT MAX(DISC_TIME) FROM Stats) / 600) * 600)

然后您需要将统计数据加入其中

JOIN Stats 
    ON Stats.CONN_TIME = Stats.CONN_TIME # Condition which is always true
    AND time.result_date + 600 > Stats.CONN_TIME # Logon is before end of timespan
    AND time.result_date < Stats.DISC_TIME  # Logoff is after beginning of timespan

并按 result_date 对整个内容进行分组。

我在这篇文章中省略了一些部分,我建议查看上面链接的 fiddle 。

希望这有帮助。

关于所有行上的 MySQL GROUP BY 条件(不是 WHERE 或 HAVING),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51751394/

相关文章:

mysql - MySQL 中表的最大命中数

MySQL JOIN 获取不存在的行

javascript - 使用 jquery 将 mysql 数据获取到新表行

PHP (5.5.7) 连接到 Windows Servers 2008 R2 中的 MySQLi 时发出警告

php - 将 mysql 查询转换为 codeigniter 事件记录

Sqlite ORDER BY 组的计数很慢

MySQL Select from UNION 性能问题(杀死数据库)

group-by - x 列包含一个解析函数,这在 GROUP BY 中是不允许的

SQL 查找单次出现的引用

MySQL - 如何将小时分组,偏移 30 分钟