我有一个表格,其中包含有关特定时间内存在的项目的数据 - 定期拍摄快照。
简单示例:
Timestamp ID
1 A
1 B
2 A
2 B
2 C
3 A
3 D
4 D
4 E
在这种情况下,项目C在快照1和2之间的某个时间创建,有时在快照2和3 B之间创建,B和C消失,D创建等等。
该表相当大(数百万条记录),每个时间戳大约有50条记录。
为两个连续时间戳之间消失的项目选择项目ID的最有效方法是什么?
所以对于上面的例子......
1到2之间:NULL
2到3之间:B,C
3到4之间:A
如果它没有使查询效率低下,是否可以扩展为自动使用最新的(即MAX)时间戳和前一个时间戳?
答案 0 :(得分:1)
<强>更新强>
有关效果详情,请参阅我的博客中的此条目:
SELECT ts,
(
SELECT GROUP_CONCAT(id)
FROM mytable mi
WHERE mi.ts =
(
SELECT MAX(ts)
FROM mytable mp
WHERE mp.ts = mo.pts
)
AND NOT EXISTS
(
SELECT NULL
FROM mytable mn
WHERE mn.ts = mo.ts
AND mn.id = mi.id
)
)
FROM (
SELECT @r AS pts,
@r := ts AS ts
FROM (
SELECT @r := NULL
) vars,
(
SELECT DISTINCT ts
FROM mytable
) moo
) mo
仅选择最后一次更改:
SELECT ts,
(
SELECT GROUP_CONCAT(id)
FROM mytable mi
WHERE mi.ts =
(
SELECT MAX(ts)
FROM mytable mp
WHERE mp.ts < mo.ts
)
AND NOT EXISTS
(
SELECT NULL
FROM mytable mn
WHERE mn.ts = mo.ts
AND mn.id = mi.id
)
)
FROM (
SELECT MAX(ts) AS ts
FROM mytable
) mo
为了提高效率,您需要在mytable (timestamp, id)
上建立一个综合索引(按此顺序)。
答案 1 :(得分:1)
另一种查看方法是,您希望查找时间戳#1中存在的时间戳#2中不存在的记录。最简单的方法?
SELECT Timestamp
FROM records AS t1
WHERE NOT EXISTS (SELECT 1 FROM records AS t2 WHERE t2.id = t1.id AND t2.Timestamp = t1.Timestamp + 1)
当然,我在这里利用你的示例时间戳是整数的事实,而实际上我认为它们是真正的时间戳。但事实证明,整数对于这个特定的目的来说效果很好,它们真的很方便。所以,也许我们应该列出所有可用时间戳的编号列表。获取 的最简单方法是什么?
CREATE TEMPORARY TABLE timestamp_map AS (
timestamp_id AS INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
timestamp_value AS DATETIME
);
INSERT INTO timestamp_map (timestamp_value) (SELECT DISTINCT timestamp FROM records ORDER BY timestamp);
(您也可以通过使用触发器永久维护这样的表。)
它有点像,但我已经得到了类似的技术,过去非常有效地处理数据,就像你描述的那样,当许多来回的子查询和NOT EXISTS
被证明太慢时。 / p>