【问题标题】:Randomly pick X objects with distinct names随机选择 X 个具有不同名称的对象
【发布时间】:2020-12-31 18:16:32
【问题描述】:

以下尝试:

Article.objects.filter(category__id="b5e20323-8cec-413a-b405-342b3809f9a4").distinct('title').order_by("?")

给我:

ProgrammingError: SELECT DISTINCT ON 表达式必须匹配初始 ORDER BY 表达式

我尝试使用原始 SQL。所以我尝试了:

SELECT * FROM (SELECT DISTINCT title from article WHERE category_id = '...') AS inner_distinct ORDER BY RANDOM() LIMIT 3

这可行,但我需要在标题中添加一个附加字段。如果我将原始查询更改为:

SELECT * FROM (SELECT DISTINCT title, id from article WHERE category_id = '...') AS inner_distinct ORDER BY RANDOM() LIMIT 3

DISTINCT 关键字突然失效了。

我该如何克服这个问题?


编辑:假设我有一个名为 Shapes 的表。这是示例数据:

ID                                      name
====================================    ========
2f3e9b34-0184-4e92-b205-88dac05b7cb0    Oval
b6382663-848a-4760-ad2a-3195977cf892    Line
e77a6a1a-7e99-4b00-97d3-df684e1bcc38    Line
ef7eb727-b4a8-43aa-b11f-1ddc5c0385fe    Triangle

提供的解决方案(SELECT * FROM (SELECT DISTINCT ON (name) name, id from shapes AS inner_distinct ORDER BY RANDOM() LIMIT 3) 总是返回以下内容(以随机顺序)

ID                                      name
====================================    ========
2f3e9b34-0184-4e92-b205-88dac05b7cb0    Oval
b6382663-848a-4760-ad2a-3195977cf892    Line
ef7eb727-b4a8-43aa-b11f-1ddc5c0385fe    Triangle

永远不会:

e77a6a1a-7e99-4b00-97d3-df684e1bcc38    Line

代替:

b6382663-848a-4760-ad2a-3195977cf892    Line

(虽然一次一个,但有时都应该被选中!)

【问题讨论】:

  • 我也会要求添加示例数据和预期结果。

标签: sql django postgresql


【解决方案1】:

使用 Postgres 中的 distinct on 这个不错的功能。

SELECT * FROM (SELECT DISTINCT ON (title) title, id from article WHERE category_id = '...') AS inner_distinct ORDER BY RANDOM() LIMIT 3

编辑:- 使用来自 OP 的最新示例数据更新查询。

我将distinct on 放在外部,将order by random() 放在内部,按预期工作。请检查。

select distinct on (name) name,id 
  from (select name, id from shapes order by random()) as inner_distinct 
order by name limit 3

**DISTINCT ON 的替代品**

使用 row_number() 我们可以实现您想要的。我已经对形状进行了测试,但您可以根据需要替换为 article

select name,id 
  from (select name, id,row_number() over (partition by name order by random()) rn 
          from shapes) i 
where i.rn = 1
order by random()
limit 3

【讨论】:

  • 这个问题是当我有多篇文章带有相同的标题时,它总是返回它们。不是随机挑选的。
  • @Adam Silver,我会要求提供一些样本数据,这将有助于更好地调查问题。
  • 谢谢 - 结束(分区...)工作(替代 DISTINCT ON 对我不起作用 - 总是相同的行)。
【解决方案2】:

原答案

在这种情况下,当您说选择不同的标题,id 时,您是在告诉它同时使用“标题”和“id”来选择不同的。所以像下面这样使用 distinct:

SELECT * FROM (SELECT DISTINCT ON (title) title, id from article WHERE category_id = '...') AS inner_distinct ORDER BY RANDOM() LIMIT 3

经过编辑以提供不同列的随机性

SELECT * FROM 
  (
    SELECT DISTINCT ON(title) title, id 
    FROM 
    (
      SELECT * from article 
      WHERE category_id = '...' 
      ORDER BY RANDOM()
    ) inner_distinct
  ) inner_random 
ORDER BY RANDOM () 
LIMIT 3

【讨论】:

  • 这个问题是当我有多篇文章带有相同的标题时,它总是返回它们。不是随机挑选的。
  • 这几乎是我需要的。唯一的问题是行不是随机排序的。如果我的数据库中有 4 个标题,其中 2 个标题相同,则其中一个重复的标题将被排除(我想要的),但标题总是以相同的顺序出现。
  • 第 3 次编辑解决方案感觉很老套,我很肯定有更好的方法可以完成,但它确实完成了工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-09
  • 2020-03-19
  • 1970-01-01
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多