【问题标题】:How to query the first row efficiently?如何高效查询第一行?
【发布时间】:2019-03-07 19:20:32
【问题描述】:

我有一个包含大量记录的表:

date          instrument    price
2019.03.07    X             1.1
2019.03.07    X             1.0
2019.03.07    X             1.2
...

当我查询当日开盘价时,我使用:

1 sublist select from prices where date = 2019.03.07, instrument = `X

执行需要很长时间,因为它选择了当天的所有价格并获得第一个。

我也试过了:

select from prices where date = 2019.03.07, instrument = `X, i = 0        //It does not return any record (why?)
select from prices where date = 2019.03.07, instrument = `X, i = first i  //Seem to work. Does it?

在 Oracle 中,等价物是:

select * from prices where date = to_date(...) and instrument = "X" and rownum = 1

Oracle 将在找到第一条记录时立即停止。

如何在 KDB 中执行此操作(例如,在找到第一条记录后立即停止)?

【问题讨论】:

  • 使用i=0 仅当您要查找的仪器是表中的第一项时才有效。使用 i=first i 时,查询将使用过滤选择中的第一个索引。
  • 您是否已向仪器列添加(或考虑添加)属性?例如,如果您要应用 `p# 属性,它应该使您的 select 语句 (instrument=X) 中的第二个子句明显更快。

标签: kdb


【解决方案1】:

在 kdb 中,select 语句中的 where 子句按顺序执行。即只有通过第一个“测试”的记录才能通过第二个测试。考虑到这一点,看看你的两次尝试:

select from prices where date = 2019.03.07, instrument = `X, i = 0        //It does not return any record (why?)

这不会(必然)返回任何东西,因为当它到达i=0 检查时,您已经过滤掉了一些记录(可能包括原始表中的第一条记录,它应该有@987654326 @)

select from prices where date = 2019.03.07, instrument = `X, i = first i  //Seem to work. Does it?

这个应该可以的。首先,您按日期过滤。然后在该日期的记录中,选择仪器`X 的记录。然后在这些记录中,您获取i 是first i 的记录(其中i 已经被过滤掉了,所以first i 只是第一条记录的索引[仍然原始表中的索引,而不是过滤后的版本])

【讨论】:

  • 如果您的意图是获得所有您可能想尝试的工具的开盘价select from prices where date=2019.03.07,i=(first;i)fby instrument,则更进一步。
  • 我刚刚使用\t 做了一个简单的测量。 1 sublist 和 i = first i 的版本需要相同的时间才能完成。如何在 Oracle 中实现rownum=1 之类的功能?
  • ? (find) 运算符可以找到您仪器的第一个实例的索引,然后将其与i 列匹配。比如:select from prices where date=2019.03.07, i=instrument?`X
  • @JorgeSawyer 那是个好方法!你想让它成为答案吗?
  • @texasbruce 如果您查看 Rahul 的回答中的 cmets,您会发现 Jorge 提出的这个解决方案实际上并不能正常工作
【解决方案2】:

Q-SQL 等效于 select[n] 在大多数情况下,它也比其他方法执行得更好。正数 'n' 将给出前 n 条记录,负数将给出最后 n 条记录。

q) select[1] from prices where date = 2019.03.07, instrument = `X

没有内置功能可以在第一次匹配后停止。您可以为此编写自定义函数,但这可能会比上述支持的版本执行得慢。

【讨论】:

  • find 运算符只找到向量的第一个匹配项,因此我们可以使用它来获得此功能:select from prices where date=2019.03.07, i=instrument?`X
  • 这行不通,而且会给出一个不可预知的答案。原因是在第一个过滤器之后,''i' 可能不是从 0 开始,但是在第二个过滤器中 find 会生成一个以 0 为基数的索引。第二个过滤器(查找)无法跟踪第一个过滤器生成的索引
  • 我们可以将其修复为:select from prices where date=2019.03.08,i=i instrument?`X。但由于 find 运算符不考虑排序属性等属性,因此与其他内置搜索相比,它在具有适当属性的大表上运行速度较慢。在普通桌子上它可以运行得更快。
  • 我曾认为i 列将在任何给定分区内从零开始。是否存在我的假设失败的特定情况,或者i 列的行为通常不可预测?
  • i 是从 0 开始的分区是正确的。对于分区数据库,它可以正常工作,但对于内存表,它不会。此外,在分区数据库的情况下,如果在日期和仪器过滤器之间添加了一个额外的过滤器,那么它将再次成为 i 不会从 0 开始并且取决于最后一个过滤器的相同情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-15
  • 2016-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多