9

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

对于 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();
4

5 回答 5

11

你要么做一个子查询

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

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

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 所需的唯一键,因此如果您按 title、cod 和可见索引(用于WHERE),很可能根本不会访问物理表。

我不太确定第二个表达式是否也会发生这种情况。

于 2012-07-09T19:39:18.543 回答
3

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

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,因为这应该是一个布尔列。

于 2012-07-09T20:48:24.850 回答
1

使用子查询。不要忘记表别名,t. LIMIT紧随其后ORDER BY

    SELECT *
    FROM (SELECT DISTINCT a, b, c
          FROM datatable WHERE a = 'hello'
         ) t
    ORDER BY random()
    LIMIT 10;
于 2019-03-17T04:39:05.177 回答
0

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

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

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

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

于 2012-07-09T18:56:34.947 回答
0
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。

于 2012-07-09T18:57:00.550 回答