好了,所以我在这里有一个学习的时刻,并找出后_一个_办法得到这个工作,我很好奇,如果任何人有更多的位Postgres的经验能帮助我想出一个办法做到这一点而不做整个幕后花絮(或对我要获取的每个商品进行一次查询)…现在进行解释:
假设我有1000条记录,我们将在具有以下字段的数据库中将它们称为“实例”:
id user_id other_id
我想创建一个可以调用的方法,该方法提取10个实例,每个实例都有一个唯一的other_id字段,用简单的英语显示(我知道这是行不通的:)):
Select * from instances where user_id = 3 and other_id is unique limit 10
因此,我希望能够在这10个实例上运行map函数并返回类似[1,2, 3,4,5,6,7,8,9,10]。
从理论上讲,尽管我正在努力避免它们,但我目前可能可以做两件事之一:
存储一个ID数组,并进行单个调用,以确保下一个调用显示“不在此数组中”。这里的问题是我正在做10个单独的数据库查询。
引入大量的说例,即50个实例,然后在红宝石土地上对它们进行排序,以找到10个唯一的实例。这将不允许我利用数据库中已经进行的任何优化,而且冒着查询50个没有10个唯一的other_id的项目的风险,除非我坚持使用,否则我将被困在其中。做了另一个查询。
无论如何,希望有人能够告诉我我忽略了一个简单的选择:)我知道这是在真正需要之前进行的 一种 优化,但是此功能将一遍又一遍地运行,所以我认为这不是一个简单的选择。现在浪费时间。
作为记录,我使用的是Ruby 1.9.3,Rails 3.2.13和Postgresql(Heroku)
谢谢!
编辑 :只是想举一个技术上可行的功能的示例(上面是第1个)
def getInstances(limit, user) out_of_instances = false available = [] other_ids = [-1] # added -1 to avoid submitting a NULL query until other_ids.length == limit || out_of_instances == true instance = Instance.where("user_id IS ? AND other_id <> ALL (ARRAY[?])", user.id, other_ids).limit(1) if instance != [] available << instance.first other_ids << instance.first.other_id else out_of_instances = true end end end
然后您将运行:
getInstances(10, current_user)
尽管这可行,但这并不理想,因为每次调用它时都会导致10个单独的查询:(
在单个SQL查询中,这可以轻松实现,SELECT DISTINCT ON...这是PostgreSQL特定的功能。
SELECT DISTINCT ON...
参见http://www.postgresql.org/docs/current/static/sql- select.html
SELECT DISTINCT ON(expression [,…])仅保留给定表达式等于的每组行的第一行。使用与ORDER BY相同的规则来解释DISTINCT ON表达式(请参见上文)。请注意,除非使用ORDER BY来确保所需的行首先出现,否则每个集合的“第一行”都是不可预测的
以您的示例为例:
SELECT DISTINCT ON (other_id) * FROM instances WHERE user_id = 3 ORDER BY other_id LIMIT 10