gpt4 book ai didi

sql - 如何编写一个选择查询或服务器端函数,从许多数据点生成一个整洁的时间流图?

转载 作者:行者123 更新时间:2023-12-04 12:58:04 25 4
gpt4 key购买 nike

注意:我正在使用图形数据库(具体来说是 OrientDB)。这让我可以自由地用 javascript 或 groovy 编写服务器端函数,而不是将自己限制在 SQL 中来解决这个问题。*

注意 2:由于这是一个图形数据库,下面的箭头只是描述数据流。我实际上不需要在查询中返回箭头。箭头代表关系。*

我有以时间流方式表示的数据;即 EventC 发生在 EventB 之后,EventB 发生在 EventA 之后,等等。这个数据来自多个来源,所以它不是完全线性的。它需要聚集在一起,这就是我遇到问题的地方。

目前数据看起来像这样:

#     |  event   |  next
--------------------------
12:0 | EventA | 12:1
12:1 | EventB | 12:2
12:2 | EventC |
12:3 | EventA | 12:4
12:4 | EventD |

其中“next”是时间流中下一个事件的 out() 边缘。在图表上,这看起来像:
EventA-->EventB-->EventC
EventA-->EventD

由于这些数据需要聚合在一起, 我需要合并重复的事件但保留它们的边缘 .换句话说,我需要一个选择查询,它将导致:
        -->EventB-->EventC
EventA--|
-->EventD

在这个例子中,由于 EventB 和 EventD 都发生在 EventA 之后(只是在不同的时间),选择查询将显示 EventA 的两个分支,而不是两个单独的时间流。

编辑 #2

如果将额外的一组数据添加到上面的数据中,使用 EventB->EventE,结果数据/图表将如下所示:
#     |  event   |  next
--------------------------
12:0 | EventA | 12:1
12:1 | EventB | 12:2
12:2 | EventC |
12:3 | EventA | 12:4
12:4 | EventD |
12:5 | EventB | 12:6
12:6 | EventE |

EventA-->EventB-->EventC
EventA-->EventD
EventB-->EventE

我需要一个查询来生成一棵树,如:
                    -->EventC
-->EventB--|
| -->EventE
EventA--|
-->EventD

编辑 #3 和 #4

这是显示边缘的数据,而不是上面的“下一个”列。我还在这里添加了几列额外的列,希望能消除对数据的任何混淆:
#     |  event   |    ip_address    |       timestamp     |   in   |  out  |
----------------------------------------------------------------------------
12:0 | EventA | 123.156.189.18 | 2015-04-17 12:48:01 | | 13:0 |
12:1 | EventB | 123.156.189.18 | 2015-04-17 12:48:32 | 13:0 | 13:1 |
12:2 | EventC | 123.156.189.18 | 2015-04-17 12:48:49 | 13:1 | |
12:3 | EventA | 103.145.187.22 | 2015-04-17 14:03:08 | | 13:2 |
12:4 | EventD | 103.145.187.22 | 2015-04-17 14:05:23 | 13:2 | |
12:5 | EventB | 96.109.199.184 | 2015-04-17 21:53:00 | | 13:3 |
12:6 | EventE | 96.109.199.184 | 2015-04-17 21:53:07 | 13:3 | |

数据是这样保存的,以保存每个单独的事件和 session 流(由 IP 地址标记)。

TL;博士

有很多事件,一些重复,需要将它们全部组织成一个整洁的时间流图。

最佳答案

天啊。

在与这个搏斗一个多星期后,我想我终于有了一个工作功能。这不是针对性能进行优化的(哦,循环!),但是在我可以处理性能的同时暂时完成了工作。生成的 OrientDB 服务器端函数(用 javascript 编写):

功能:

// Clear previous runs
db.command("truncate class tmp_Then");
db.command("truncate class tmp_Events");

// Get all distinct events
var distinctEvents = db.query("select from Events group by event");

// Send 404 if null, otherwise proceed
if (distinctEvents == null) {
response.send(404, "Events not found", "text/plain", "Error: events not found" );
} else {
var edges = [];

// Loop through all distinct events
distinctEvents.forEach(function(distinctEvent) {
var newEvent = [];
var rid = distinctEvent.field("@rid");
var eventType = distinctEvent.field("event");

// The main query that finds all *direct* descendents of the distinct event
var result = db.query("select from (traverse * from (select from Events where event = ?) where $depth <= 2) where @class = 'Events' and $depth > 1 and @rid in (select from Events group by event)", [eventType]);

// Save the distinct event in a temp table to create temp edges
db.command("create vertex tmp_Events set rid = ?, event = ?", [rid, event]);
edges.push(result);
});

// The edges array defines which edges should exist for a given event
edges.forEach(function(edge, index) {
edge.forEach(function(e) {
// Create the temp edge that corresponds to its distinct event
db.command("create edge tmp_Then from (select from tmp_Events where rid = " + distinctEvents[index].field("@rid") + ") to (select from tmp_Events where rid = " + e.field("@rid") + ")");
});
});

var result = db.query("select from tmp_Events");
return result;
}

要点:
  • 临时表似乎是必要的。 我尝试在没有临时表(类)的情况下执行此操作,但我不确定是否可以完成。我需要模拟原始数据中不存在的边缘。
  • Traverse 在编写主查询时非常有帮助。 遍历一个事件以找到它的直接、独特的后代是相当简单的。
  • 能够在 Javascript 中编写存储过程真是太棒了。 这在 SQL 中将是一场噩梦。
  • omfg 循环。 我计划优化它并继续让它变得更好,所以希望其他人可以找到它的用处。
  • 关于sql - 如何编写一个选择查询或服务器端函数,从许多数据点生成一个整洁的时间流图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29583040/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com