如何在 PostgreSQL 中将 SELECT DISTINCT 与 RANDOM() 函数一起使用?

Mar*_*ato 8 sql postgresql select

我正在尝试运行 SQL 查询以获取四个随机项目。由于表中product_filter有多个touple,product我必须使用DISTINCTin SELECT,所以我收到此错误:

对于 SELECT DISTINCT,ORDER BY 表达式必须出现在选择列表中

但如果我把它放在RANDOM()我的SELECT里面,它会避免DISTINCT结果。

有人知道怎么DISTINCT用这个RANDOM()函数吗?下面是我有问题的查询。

SELECT DISTINCT
    p.id, 
    p.title
FROM
    product_filter pf
    JOIN product p ON pf.cod_product = p.cod
    JOIN filters f ON pf.cod_filter = f.cod
WHERE
    p.visible = TRUE
LIMIT 4
ORDER BY RANDOM();
Run Code Online (Sandbox Code Playgroud)

LSe*_*rni 8

你要么做一个子查询

SELECT * FROM (
    SELECT DISTINCT p.cod, p.title ... JOIN... WHERE
    ) ORDER BY RANDOM() LIMIT 4;
Run Code Online (Sandbox Code Playgroud)

或者您尝试对这些相同的字段进行分组:

SELECT p.cod, p.title, MIN(RANDOM()) AS o FROM ... JOIN ...
    WHERE ... GROUP BY p.cod, p.title ORDER BY o LIMIT 4;
Run Code Online (Sandbox Code Playgroud)

这两个表达式中哪一个计算得更快取决于表结构和索引;通过对 cod 和 title 进行适当的索引,子查询版本将运行得更快(cod 和 title 将从索引基数信息中获取,并且 cod 是 JOIN 所需的唯一键,因此如果您按标题、cod 和可见(用于WHERE),很可能根本就不会访问物理表。

我不太确定这是否也会发生在第二个表达式中。


Erw*_*ter 4

简化查询以避免先验问题:

SELECT p.cod, p.title
FROM   product p
WHERE  p.visible
AND    EXISTS (
    SELECT 1
    FROM   product_filter pf
    JOIN   filters f ON f.cod = pf.cod_filter
    WHERE  pf.cod_product = p.cod
    )
ORDER  BY random()
LIMIT  4;
Run Code Online (Sandbox Code Playgroud)

结果中只有表中的列product,仅检查其他表是否存在匹配的行。对于这样的情况,EXISTS表达式可能是最快且最简单的。它不会增加基表中的行product,因此您无需使用 再次删除它们DISTINCT

LIMIT必须排在最后,之后ORDER BY

我简化WHERE p.visible = 't'WHERE p.visible同样的事情,只是专栏的 cheoper boolean