【问题标题】:SQL Query to Group Clusters of Related Events with Criteria使用条件对相关事件集群进行分组的 SQL 查询
【发布时间】:2014-09-02 17:29:57
【问题描述】:

好的,如果不在白板或其他东西上画出来,这很难解释......但它就是这样。我试图尽可能清楚,但如果这没有意义,请告诉我......

我有一个 MS Access 项目,它处理来自多个源对象或“源”和多个观察点或“接收器”的时间序列数据集,并根据时间和空间接近度识别感兴趣的事件。这为我提供了一个包含以下字段的可能相关事件的触发器表。

CORRELATION_ID
RECEIVER_EVENT_ID
RECEIVER_NAME
RECEIVER_START_DATETIME
RECEIVER_END_DATETIME
SOURCE_EVENT_ID
SOURCE_NAME
SOURCE_START_DATETIME
SOURCE_END_DATETIME

因为我可以在重叠时间或彼此接近的时间发生多个源和接收器触发器,所以我得到了一个庞大的触发器列表,我想通过进一步分组来优化这个触发器列表标准。

我想为源事件之间的最大允许时间间隔 MAX_SOURCE_GAP 和接收器事件之间的最大允许间隔 MAX_RECEIVER_GAP 指定 2 个标准。 GAP 的计算方法是从一个触发器的开始时间减去另一个触发器的结束时间。

如果事件在此间隔范围内,则需要对其进行分组,并且生成的组记录必须存储最早事件的开始时间和最新事件的结束时间。对于 RECEIVER 事件,RECEIVER_NAME 必须相同。 (即我不想对来自不同接收者的事件进行分组,因为我仍然希望得到相关接收者源事件的列表)对于源事件,事件必须由同一个接收者接收,换句话说,接收者名称再次必须相同。我还希望记录返回分组的源的名称列表。为此,我想我可以实现 Allen Browne 的 ConcatRelated() 函数。

更新所需的第三个标准定义了分组源事件和分组接收器事件之间的关系,MAX_SOURCE_TO_RECEIVER_DELAY。这是接收器可以被触发的源开始时间之后的最大允许时间延迟。换句话说,startTime_receiver - startTime_source

我认为基本上这需要几个步骤。至少一个子查询来对 SOURCE 事件进行分组。至少一个子查询来对 RECEIVER 事件进行分组。然后是合并它们的步骤,这样我就可以返回这样的东西。

RECEIVER_NAME
MIN-RECEIVER_START_DATETIME
MAX-RECEIVER_END_DATETIME
MIN-SOURCE_END_DATETIME
MAX-SOURCE_END_DATETIME
LIST_OF_SOURCES
Allen Browne's ConcatRelated() function 生成的看起来像“SOURCE10、SOURCE 24、SOURCE 51”的字段。

我想我理解方法,但我无法正确分组有超过 2 个触发器的事物。如果我弄清楚了正确的时间分组,我可能可以解决将源名称与 ConcatRelated 连接起来的问题。

--更新- 我已将一些示例数据上传到 SQLfiddle.com click here for sample dataset

对于这个示例数据集,我基本上试图得出的结果表如下所示:


RECEIVER_NAME MIN-RECEIVER_START_DATETIME MAX-RECEIVER_END_DATETIME SOURCE_LIST MIN-SOURCE_START_DATETIME MAX-SOURCE_END_DATETIME
RECEIVER1 2012-04-08 05:08 2012-04-08 06:22 SOURCE1,SOURCE2,SOURCE3 2012-04-08 02:10 2012-04-08 05:25
RECEIVER2 2012-05-08 10:05 2012-04-08 14:55 SOURCE1,SOURCE2 2012-05-08 10:01 2012-05-08 13:45
RECEIVER2 2012-06-08 06:55 2012-06-08 21:19 SOURCE2 2012-05-08 14:55 2012-05-08 16:22

抱歉,哇,想张贴一张桌子真是太痛苦了。我找不到更好的方法。

【问题讨论】:

  • (1) 选择您使用的数据库,SQL Server 或 MS Access; (2) 如果您无法解释某事,请展示示例数据和所需结果。
  • 从 sqlfiddle.com 开始,这是一个将示例数据放在一起的好地方。
  • 你的逻辑有几个问题:因为你有两个标准,你仍然会产生重复的记录。第二个问题是:按 max_allowed_time_Gap 对开始和结束时间进行分组,无论它们的开始和结束时间如何,都会对它们进行分组。例如: max_allowed_gap = 10mins: st01:00, et01:10 和 st02:00, et02:10 将被组合在一起。你可以做什么:将标准减少到(receiver_start_time)和(REceiver_end_time)之间的记录,你有机会从接收器和源日期时间获取最小值和最大值。按时间线分组,然后每小时触发一次。
  • @krish-km 这是有道理的,我意识到我遗漏了将源事件和接收器事件关联起来的标准,即源触发和接收器触发之间的最大延迟时间。我已经在上面添加了...
  • @user1243468:你真的必须在访问中这样做吗?因为 Access/Jet 并不以此类操作而闻名。这并不意味着您不能在 Access 中执行此操作。 Access 可能会花时间处理其他 SQL 引擎可以轻松完成的操作。

标签: sql ms-access vba ms-access-2010


【解决方案1】:

正如我在评论中提到的,no 标准已用于产生结果。您的事件按 RECEIVER_EVENT_ID 和 RECEIVER_EVENT_START_TIME 分组。 (我猜receiver_event_id 总是与receiver_name 相关,因此我选择了event_id 但您也可以按receiver_name 分组,由您决定)

这将给现在:

  1. 240 |接收器1 | 2012 年 8 月 4 日 05:08:00+0000
  2. 241 |接收器2 | 2012 年 8 月 5 日 10:05:00+0000
  3. 242 |接收器2 | 2012 年 8 月 5 日 14:15:00+0000
  4. 243 |接收器2 | 2012 年 8 月 6 日 06:55:00+0000

然后您可以找到与正在分组的事件相关的最小值和最大值。 如果您想对事件 241 和 242 进行分组,则需要找到将它们组合在一起的逻辑。

这里是分组事件和事件开始时间的代码markdown:

希望这能让您了解 MySQL 中的 group_concatenation 函数以及分组。如果您找到了适合您问题的确切 SQL 语句或更快的解决方案,请告诉我。我也很感兴趣。

SQL Fiddle

MySQL 5.5.32 架构设置

CREATE TABLE relatedEvents 
    (
     CORRELATION_ID INT auto_increment primary key, 
     RECEIVER_EVENT_ID INT,
     RECEIVER_NAME VARCHAR(20), 
     RECEIVER_START_DATETIME DATETIME,
     RECEIVER_END_DATETIME DATETIME,
     SOURCE_EVENT_ID INT,
     SOURCE_NAME VARCHAR(20),
     SOURCE_START_DATETIME DATETIME,
     SOURCE_END_DATETIME DATETIME
    );

INSERT INTO relatedEvents
(RECEIVER_EVENT_ID, RECEIVER_NAME, RECEIVER_START_DATETIME, 
  RECEIVER_END_DATETIME, SOURCE_EVENT_ID, SOURCE_NAME, SOURCE_START_DATETIME, SOURCE_END_DATETIME)
VALUES
('240', 'RECEIVER1', '2012-08-04 05:08:00', '2012-08-04 06:22', '1', 'SOURCE1', '2012-08-04 02:10', '2012-08-04 02:40'),
('240', 'RECEIVER1', '2012-08-04 05:08:00', '2012-08-04 06:22', '2', 'SOURCE2', '2012-08-04 02:30', '2012-08-04 03:10'),
('240', 'RECEIVER1', '2012-08-04 05:08:00', '2012-08-04 06:22', '3', 'SOURCE2', '2012-08-04 03:15', '2012-08-04 03:30'),
('240', 'RECEIVER1', '2012-08-04 05:08:00', '2012-08-04 06:22', '4', 'SOURCE3', '2012-08-04 05:01', '2012-08-04 05:25'),
('241', 'RECEIVER2', '2012-08-05 10:05:00', '2012-08-05 10:35', '5', 'SOURCE1', '2012-08-05 10:01', '2012-08-05 10:15'),
('241', 'RECEIVER2', '2012-08-05 10:05:00', '2012-08-05 10:35', '6', 'SOURCE2', '2012-08-05 12:15', '2012-08-05 12:17'),
('242', 'RECEIVER2', '2012-08-05 14:15:00', '2012-08-05 14:55', '7', 'SOURCE1', '2012-08-05 13:35', '2012-08-05 13:45'),
('243', 'RECEIVER2', '2012-08-06 06:55:00', '2012-08-06 21:19', '8', 'SOURCE2', '2012-08-05 14:55', '2012-08-05 16:22');

查询 1

SELECT
  RECEIVER_EVENT_ID as EVENT_ID,
  o_r.receiver_name as Receiver_name,
  (select min(RECEIVER_START_DATETIME)from relatedEvents as I_R where ((I_R.RECEIVER_EVENT_ID = O_R.RECEIVER_EVENT_ID)) Group by I_R.RECEIVER_EVENT_ID)as min_r_st,
  (select Max(RECEIVER_END_DATETIME)from relatedEvents as I_R where ((I_R.RECEIVER_EVENT_ID = O_R.RECEIVER_EVENT_ID)) Group by I_R.RECEIVER_EVENT_ID) as max_r_et,
  (Select group_concat(DISTINCT source_name) from relatedEvents as I_R where ((I_R.RECEIVER_EVENT_ID = O_R.RECEIVER_EVENT_ID)) Group by I_R.RECEIVER_EVENT_ID) as Sources,
  (select min(SOURCE_START_DATETIME)from relatedEvents as I_R where ((I_R.RECEIVER_EVENT_ID = O_R.RECEIVER_EVENT_ID)) Group by I_R.RECEIVER_EVENT_ID)as min_s_st,
  (select Max(SOURCE_END_DATETIME)from relatedEvents as I_R where ((I_R.RECEIVER_EVENT_ID = O_R.RECEIVER_EVENT_ID)) Group by I_R.RECEIVER_EVENT_ID) as max_s_et,
  count(RECEIVER_START_DATETIME) as RST
FROM relatedEvents as O_R
group by RECEIVER_EVENT_ID, RECEIVER_START_DATETIME
order by RECEIVER_START_DATETIME asc

Results

| EVENT_ID | RECEIVER_NAME |                      MIN_R_ST |                      MAX_R_ET |                 SOURCES |                      MIN_S_ST |                      MAX_S_ET | RST |
|----------|---------------|-------------------------------|-------------------------------|-------------------------|-------------------------------|-------------------------------|-----|
|      240 |     RECEIVER1 | August, 04 2012 05:08:00+0000 | August, 04 2012 06:22:00+0000 | SOURCE1,SOURCE2,SOURCE3 | August, 04 2012 02:10:00+0000 | August, 04 2012 05:25:00+0000 |   4 |
|      241 |     RECEIVER2 | August, 05 2012 10:05:00+0000 | August, 05 2012 10:35:00+0000 |         SOURCE1,SOURCE2 | August, 05 2012 10:01:00+0000 | August, 05 2012 12:17:00+0000 |   2 |
|      242 |     RECEIVER2 | August, 05 2012 14:15:00+0000 | August, 05 2012 14:55:00+0000 |                 SOURCE1 | August, 05 2012 13:35:00+0000 | August, 05 2012 13:45:00+0000 |   1 |
|      243 |     RECEIVER2 | August, 06 2012 06:55:00+0000 | August, 06 2012 21:19:00+0000 |                 SOURCE2 | August, 05 2012 14:55:00+0000 | August, 05 2012 16:22:00+0000 |   1 |

【讨论】:

  • 谢谢,我正在寻找的输出是相似的,除了标准它可能对其中一些结果进行不同的分组。如果 MAX_RECEIVER_GAP = 12 小时、MAX_SOURCE_GAP = 6 小时和 MAX_SOURCE_TO_RECEIVER_DELAY = 18 小时,则它将 event_ID 241 和 242 分组,因为标准适用于接收器、源和源-接收器延迟。
  • 另外,由于我没有 MYSQL 功能,我必须找到一种方法让它在 MS Access 中工作。但是如果我们可以在 MYSQL 中解决它,我可以尝试让它在访问 SQL 中工作。
  • @user1243468:我不知道你的确切要求。你可能比我知道的更多。你现在有了一个起点。摆弄它 :) 另请注意:组函数仅在值相同时才起作用。这意味着您的逻辑/功能必须在所有记录中返回相似的值才能组合在一起。哦,是的访问!!!!祝你好运:)
  • 感谢您的帮助。您当然更精通 SQL 我只在需要时尝试将事物组合在一起。我会试试看能不能让它工作。
猜你喜欢
  • 2022-08-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-22
  • 2020-05-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多