繁体   English   中英

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

[英]How to use SELECT DISTINCT with RANDOM() function in PostgreSQL?

我正在尝试运行 SQL 查询以获取四个随机项目。 由于表product_filterproduct有不止一个 touple 我必须在SELECT使用DISTINCT ,所以我得到这个错误:

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

但是如果我将RANDOM()放在我的SELECT ,它将避免DISTINCT结果。

有人知道如何将DISTINCTRANDOM()函数一起使用吗? 下面是我有问题的查询。

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();

你要么做一个子查询

SELECT * FROM (
    SELECT DISTINCT p.cod, p.title ... JOIN... WHERE
    ) ORDER BY RANDOM() LIMIT 4;

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

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

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

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

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

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;

要点:

  • 结果中只有表product中的列,其他表只检查匹配行的存在。 对于这种情况, EXISTS半连接可能是最快和最简单的解决方案。 使用它不会将基表product行相乘,因此您不需要再次使用DISTINCT删除它们。

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

  • 我将 WHERE p.visible = 't'简化为p.visible ,因为这应该是一个布尔列。

使用子查询。 不要忘记表别名t LIMITORDER BY

    SELECT *
    FROM (SELECT DISTINCT a, b, c
          FROM datatable WHERE a = 'hello'
         ) t
    ORDER BY random()
    LIMIT 10;

我认为你需要一个子查询:

select *
from (select DISTINCT p.cod, p.title
      from product_filter pf  join
           product p
           on pf.cod_product = p.cod
      where p.visible = 't'
     ) t
LIMIT 4
order by RANDOM()

首先计算不同的值,然后进行限制。

请注意,这确实会影响性能,因为在选择您想要的内容之前,此查询会对所有内容进行不同的处理。 这是否重要取决于您的表的大小以及您如何使用查询。

SELECT DISTINCT U.* FROM
(

    SELECT p.cod, 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 = 't' 

    ORDER BY RANDOM()

) AS U

LIMIT 4

这首先执行 RANDOM,然后执行 LIMIT。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM