小编典典

在具有唯一字段的PostgreSQL查询中返回前X条记录

sql

好了,所以我在这里有一个学习的时刻,并找出后_一个_办法得到这个工作,我很好奇,如果任何人有更多的位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]。

从理论上讲,尽管我正在努力避免它们,但我目前可能可以做两件事之一:

  1. 存储一个ID数组,并进行单个调用,以确保下一个调用显示“不在此数组中”。这里的问题是我正在做10个单独的数据库查询。

  2. 引入大量的说例,即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个单独的查询:(


阅读 205

收藏
2021-04-28

共1个答案

小编典典

在单个SQL查询中,这可以轻松实现,SELECT DISTINCT ON...这是PostgreSQL特定的功能。

参见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
2021-04-28