【问题标题】:How do I query on a subset of ActiveModel records?如何查询 ActiveModel 记录的子集?
【发布时间】:2015-02-13 22:52:12
【问题描述】:

我已经重写了这个问题,因为我之前的解释引起了混乱。

在 SQL 世界中,您有一个应用查询的初始记录集。此查询的输出是结果集。通常,初始记录集是整个记录表,结果集初始记录集中匹配查询规则集的记录.

我有一个用例,我需要我的应用程序偶尔只对表中的记录子集进行操作。如果一个表中有 10,000 条记录,我希望我的应用程序表现得像只存在前 1,000 条记录。每次这些应该是相同的 1,000 条记录。换句话说,我希望 初始记录集 是表中的前 1,000 个设备(按主键排序时),结果集是这些设备的结果记录前 1000 台设备。

已经提出了一些解决方案,并且发现我最初的描述不是很清楚。更明确地说,我并不是要实现分页。我也没有试图限制我收到的结果数量(.limit(1,000) 确实可以实现)。

谢谢!

【问题讨论】:

  • 您能详细说明您要涵盖的用例吗?我不明白您是试图只处理前 4 个条目,还是只想处理前四个条目之外的条目。
  • 我不知道如何打断你的问题,因为这没什么意义。你的最终目标是什么?要分页吗?
  • 简单地说,我想查询一个表的一个小节,而不是整个表。例如,我正在寻找“从表中的前 100 条记录中返回 some_attribute=100 的记录(按id 排序时)”的查询。
  • 看来这里Device.limited.limit(5).offset(5)你尽量不要得到空数组,而是选择5记录,以5开头,因为最新的条件只是改变了prevoius或使其更窄。得到空数组的原因是什么?

标签: ruby-on-rails database ruby-on-rails-4 activerecord arel


【解决方案1】:

这是你问题中我不明白的那一行:

这会导致两个调用出现问题,因为 limit 限制了查询的结果,而不是执行查询的数据库行。

这不是 Rails 的事情,这是 SQL 的事情。

Device.limit(n) 运行 SELECT * FROM device LIMIT n

Limit 总是返回查询结果集的子集。

first(n) 会完成你想要的吗?它既会按 PK 对结果集进行升序排序,也会限制返回的结果数。

【讨论】:

  • 这越来越近了。我想限制查询集,而不是结果集。
  • @YWCAHello 你将如何使用 SQL 来做到这一点?
  • 好问题!不幸的是,我没有答案。
  • @YWCA你好对不起,但这是我问的一个加载问题。我可以看到您完成您想要的唯一方法是从数据库中删除您不想查询的所有记录。除非你有健壮的索引和具体的where 条件,否则你最终会进行全表扫描并限制结果集。
  • 在这种情况下,假设我们想通过.order(:id).limit(100) 之类的方式选择前 x 条记录。如果我们得到id_val = Object.order(:id).limit(1).offset(100).first.id 的值,我们就不能通过将.where("id < ?", id_val) 添加到链的前面来执行我们想要的查询吗?您能想出任何巧妙的方法在单个查询中执行此操作吗? @tagCincy
【解决方案2】:

SQL 语句可以链接在一起。因此,如果您有您的子集,则可以使用它执行其他查询。

my_subset = Device.where(family: "Phone")
# SQL: SELECT * FROM Device WHERE `family` = "Phone"

my_results = my_subset.where(style: "Touchscreen")
# SQL: SELECT * FROM Device WHERE `family` = "Phone" AND `style` = "Touchscreen"

也可以写成:

my_results = Device.where(family: "Phone").where(style: "Touchscreen")
my_results = Device.where(family: "Phone", style: "Touchscreen")
# SQL: SELECT * FROM Device WHERE `family` = "Phone" AND `style` = "Touchscreen"

根据您的问题,如果您想选择前 1,000 行(按主键排序,pkey)然后对其进行查询,您需要这样做:

my_results = Device.find_by_sql("SELECT * 
                           FROM (SELECT * FROM devices ORDER BY pkey ASC LIMIT 1000) 
                           WHERE `more_searching` = 'happens here'")

【讨论】:

  • 我已将问题更新为更清晰。我不是要限制返回的结果数,而是要限制我查询的初始记录数为表中的第一个 x 记录。
  • 在 sql 中,您需要对整个数据集进行某种查询以获取您的数据子集,然后您可以对其进行任何操作。此查询仅返回前 1,000 条记录或检查某些列。
  • 不可能查询“神奇”的行子集,因为它不知道要查询哪个子集,在您的(修订后的)问题中,您提到了前 1000 行,因此您的查询将用于获取前 1000 行作为您的子集,然后针对它执行其余的查询。
  • 我不记得使用过“魔法”这个词。是否可以将前 1000 行查询与辅助查询结合起来,还是必须是两步过程?我试图避免将第一个查询的所有行返回给应用程序。
  • 对新的可能解决方案的更新答案
【解决方案3】:

您可以专门要求一组 ID:

Device.where(id: (1..4).to_a)

这将构造一个WHERE 子句,例如:

WHERE id IN (1,2,3,4)

【讨论】:

  • 不需要在where 中将范围传递给to_a 函数
  • 唯一的区别是范围会导致查询构建 BETWEEN 子句而不是 IN。
  • 我不是直接尝试查询对象 1-4,而是尝试查询前四个对象。在这种情况下,它们恰好是相同的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多