嘿。考虑下表和数据......
in_timestamp | out_timestamp | name | in_id | out_id | in_server | out_server | status
timestamp1 | timestamp2 | data1 |id1 | id2 | others-server1 | my-server1 | success
timestamp2 | timestamp3 | data1 | id2 | id3 | my-server1 | my-server2 | success
timestamp3 | timestamp4 | data1 | id3 | id4 | my-server2 | my-server3 | success
timestamp4 | timestamp5 | data1 | id4 | id5 | my-server3 | others-server2 | success
问题:
1)我需要将这个可登录形式的日志提供给客户,在那里他不需要知道关于'my-servers'的一堆信息。我应该给出的是我的基础设施和离开时的数据的时间戳;深入了解以下信息。
in_timestamp (of 'others_server1' to 'my-server1')
out_timestamp (of 'my-server3' to 'others-server2')
name
status
我想写同样的sql!有人可以帮忙吗? 注意:可能不会有3个'my-servers'。它因情况而异。例如例如,data2可能涉及4个“我的服务器”!
2)SQL还有其他替代方案吗?我的意思是存储过程/等?
3)优化? (记录数量巨大!到目前为止,每天大约有500万。我们应该显示长达一周的记录。)
事先,感谢帮助! :)
答案 0 :(得分:2)
WITH RECURSIVE foo AS
(
SELECT *, in_timestamp AS timestamp1, 1 AS hop, ARRAY[in_id] AS hops
FROM log_parsing.log_of_sent_mails
WHERE in_server = 'other-server1'
UNION ALL
SELECT t_alias2.*, foo.timestamp1, foo.hop + 1, hops || in_id
FROM foo
JOIN log_parsing.log_of_sent_mails t_alias2
ON t_alias2.in_id = (foo.t_alias1).out_id
)
SELECT *
FROM foo
ORDER BY
hop DESC
LIMIT 1
答案 1 :(得分:1)
你的桌子有一个层次结构(邻接列表)。这可以在PostgreSQL v8.4及更高版本中使用递归CTE有效查询。 Quassnoi撰写了一篇关于如何实施该文件的blog post。这是一个非常复杂的查询,您需要编写,但他用非常类似于您需要的示例解释它。特别是如果你看看他的最后一个例子,他演示了一个查询,而不是通过使用数组获得从第一个节点到最后一个节点的完整路径。
答案 2 :(得分:0)
这样做的一种方式 - 如果数据是稳定的(例如永远不会更改插入的on)是计算飞行中的传递关系(例如通过触发器或插入的应用程序) )在插入时间。
E.g。你的表中有一个新列“start_ts”;插入记录时:
in_timestamp | out_timestamp | name | in_id | out_id | in_server | out_server | status
timestamp3 | timestamp4 | data1 | id3 | id4 | my-server2 | my-server3 | success
...然后您的逻辑会自动找到包含name=data1
和out_id=id3
的记录,并将其start_ts
克隆到新插入的记录中。您可能需要一些特殊的逻辑来传播最后的状态,具体取决于您如何计算这些传递值。
顺便说一句,您无需查询上一个(name=data1
和out_id=id3
)记录 - 您可以在处理时将start_ts
值保留在数据记录的元数据本身中。
然后最终的报告只是select start_ts, out_ts from T where out_server=others_server2
(当然,就out_server和状态来说更复杂,但仍然是一个简单的选择)
第二个选项当然是更简单的循环计算结果报告 - 如果您不确定如何,对于SQL BFS实施,谷歌或“堆栈”(现在是一个可接受的动词?)
答案 3 :(得分:0)
@Other Readers:
请参阅Mark Byers首先发布的第一个答案。我使用'回答'而不是'评论'他的帖子,因为我需要使用表格/链接等,这在评论答案时是不可用的。 :)
@Mark Byers:
感谢您的链接...它真的帮助了我,我能够找到在服务器之间生成路径的方法......看看@我能做什么。
in_id | in_timestamp | out_timestmap | name | hops_count | path |
id1 | timestamp1 | timestamp2 | data1 | 1 | {id1} |
id2 | timestamp2 | timestamp3 | data1 | 2 | {id1,id2} |
id3 | timestamp3 | timestamp4 | data1 | 3 | {id1,id2,id3} |
id4 | timestamp4 | timestamp2 | data1 | 4 | {id1,id2,id3,id4} |
*路径是使用'in_id'生成的
我使用了以下查询...
WITH RECURSIVE foo AS
(
SELECT t_alias1, 1 AS hops_count, ARRAY[in_id] AS hops
FROM log_parsing.log_of_sent_mails t_alias1
WHERE in_server = 'other-server1'
UNION ALL
SELECT t_alias2, foo.hops_count + 1 AS hops_count, hops || in_id
FROM foo
JOIN log_parsing.log_of_sent_mails t_alias2
ON t_alias2.in_id = (foo.t_alias1).out_id
)
SELECT (foo.t_alias1).in_id,
(foo.t_alias1).name,
(foo.t_alias1).in_timestamp,
hops_count,
hops::VARCHAR AS path
FROM foo ORDER BY hops
但我还没达到最终阶段。这是我最终希望得到的......
in_id | in_timestamp | out_timestmap | name | hops_count | path |
id4 | timestamp1 | timestamp5 | data1 | 4 | {id1,id2,id3,id4}|
*观察时间戳。它是必需的,因为我不希望客户知道内部基础设施。所以对他而言,时间戳1和时间戳5之间的时间延迟才是最重要的。
任何线索我怎么可能实现它!?
P.S。我也会尝试联系Quassnoi。 :)