我希望能够定位一条记录,并获取该记录,并在其每一侧记录可变数量的记录。
比如说你的密钥ID是2356.所以你需要2356和2356之前和之后的3条记录,并在create_ts
上订购(例如)。
我想知道是否有办法在一个查询(mysql)中执行此操作?
答案 0 :(得分:2)
表(称之为mytable)必须在create_ts和id
上有一个复合索引ALTER TABLE mytable ADD INDEX create_ts_id_index (create_ts,id);
你显然需要两个查询来获取所需的密钥:3在id之前,id本身,3在id之后。
那是7个ids。
此查询选择4个键(id + 3 after)
SELECT create_ts,id FROM mytable WHERE id >= 2356 ORDER BY create_ts LIMIT 4;
此查询选择4个密钥(之前为id + 3)
SELECT create_ts,id FROM mytable WHERE id < 2356 ORDER BY create_ts DESC LIMIT 4;
两个查询的UNION应该删除id 2356
的副本让我们将这些结合起来并执行它的INNER JOIN到mytable
SELECT B.* FROM
(
SELECT * FROM
(SELECT create_ts,id FROM mytable
WHERE id >= 2356 ORDER BY create_ts
LIMIT 4) AA
UNION
(SELECT create_ts,id FROM mytable
WHERE id <= 2356 ORDER BY create_ts DESC
LIMIT 4)
) A
INNER JOIN mytable B USING (create_ts,id)
ORDER BY A.create_ts,A.id;
子查询A应该只有7个键。一旦检索到这7个键,INNER JOIN应该很快。
如果此次查询之前需要N个密钥和N个密钥,请使用LIMIT N+1
。
我建议使用这种方法,因为我们既不能假设3键返回是id-3,也不能假设3键后面是id + 3。如果表因任何原因在ID中存在间隙,则尤其如此。
试一试!!!
CAVEAT:我没试过。这是你想要的算法。 MySQL语法可能允许也可能不允许。它的语法不对,我将尝试构造一个示例并修复语法。
以防万一,这是一种更稳定的方法。
CREATE TABLE create_ts_ids SELECT create_ts,id FROM mytable WHERE 1=2;
ALTER TABLE create_ts_ids ADD PRIMARY KEY (id);
INSERT INTO create_ts_ids
SELECT create_ts,id FROM mytable
WHERE id >= 2356 ORDER BY create_ts LIMIT 4;
INSERT IGNORE INTO create_ts_ids
SELECT create_ts,id FROM mytable
WHERE id <= 2356 ORDER BY create_ts DESC LIMIT 4;
SELECT B.* FROM create_ts_ids A
INNER JOIN mytable B USING (create_ts,id)
ORDER BY A.create_ts,A.id;
答案 1 :(得分:-1)
如果您的选择标准只是id:
SELECT *
FROM table
WHERE key_id <= target_id + 3
AND key_id >= target_id - 3
ORDER BY create_ts;
将3替换为目标记录周围所需的记录数。