簡體   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