SELECT * from routes where start = 'A' and end = 'B' and validFrom <= x and validTo >= y
由于 Cassandra 将其数据存储在磁盘上的方式,它无法为这样的查询提取连续范围的行。所以你需要做的是稍微调整你的模型。
CREATE TABLE routes (
start text,
end text,
valid timestamp,
toFrom text,
name text,
PRIMARY KEY (start, end, valid, toFrom)
);
通过将到/从valid 时间合并到一个列中,您现在可以对其执行范围查询,检查开始和结束。每行需要存储两次。一次是“有效期至”时间,一次是“有效期自”时间。 toFrom 列有助于区分这一点。
现在我可以运行这个查询了:
> SELECT * FROM routes
WHERE start='A' AND end='B'
AND valid>='2016-02-01'AND valid<='2016-02-20';
start | end | valid | tofrom | name
-------+-----+--------------------------+--------+---------
A | B | 2016-02-01 06:00:00+0000 | F | combo 1
A | B | 2016-02-14 06:00:00+0000 | T | combo 1
A | B | 2016-02-15 06:00:00+0000 | F | combo 2
(3 rows)
只是一个想法,但使用复合分区键(如PRIMARY KEY ((start, end), valid, toFrom))来更好地分配数据可能是有意义的。尽管这实际上取决于您的查询模式....因此,如果您需要查询以“A”开头的所有行(例如),这将不起作用。
编辑 20160221
我接受了你的回答,但现在我想了更多,我认为这不会奏效。例如。我认为查询: SELECT * FROM routes WHERE start='A' AND end='B' AND valid>='2016-02-01' AND valid
实际上,确实工作:
> SELECT * FROM routes
WHERE start='A' AND end='B'
AND valid>='2016-02-01'AND valid<='2016-02-13';
start | end | valid | tofrom | name
-------+-----+--------------------------+--------+---------
A | B | 2016-02-01 06:00:00+0000 | F | combo 1
(1 rows)
话虽如此,我明白你的意思。如果您应该选择在有效到/从(不包括在内)之间发生的时间段,它将产生零行......像这样:
> SELECT * FROM routes
WHERE start='A' AND end='B'
AND valid>='2016-02-02'AND valid<='2016-02-13';
start | end | valid | tofrom | name
-------+-----+--------------------------+--------+---------
(0 rows)
这是一个合理的担忧。关于这一点的两点:
就您要求“等同于以下 SQL 语句” 的问题而言,您在关系数据库中仍然会遇到同样的问题(在我的 MariaDB 测试实例上尝试过) )。实际上,情况会更糟,因为 valid>='2016-02-01'AND valid<='2016-02-13' 的查询在 Cassandra 中返回一行,但 validFrom>='2016-02-01' AND validTo<='2016-02-13' 在 MariaDB 中没有返回任何内容。
这确实成为一个业务逻辑问题,与您的数据存储无关。为避免此问题,您应该查看您的业务逻辑/需求,并确定valid 与/从之间的最长时间。然后,您可以调整查询,使其始终超过该时间。示例:如果路由最多只能在两三周内有效,那么一次查询一个月就足够了。