选择时间戳快照之间更改的最有效方法

时间:2009-08-19 13:03:32

标签: sql mysql

我有一个表格,其中包含有关特定时间内存在的项目的数据 - 定期拍摄快照。

简单示例:

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)时间戳和前一个时间戳?

2 个答案:

答案 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>