9

SQLクエリを実行して4つのランダムなアイテムを取得しようとしています。テーブルproduct_filterには複数のtoupleが含まれているため、でproduct使用する必要DISTINCTSELECTあるため、次のエラーが発生します。

SELECT DISTINCTの場合、ORDERBY式は選択リストに表示される必要があります

しかし、私が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();
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;

2つの式のどちらがより速く評価されるかは、テーブルの構造とインデックス付けによって異なります。codとtitleに適切なインデックスを付けると、サブクエリバージョンの実行速度が速くなります(codとtitleはインデックスのカーディナリティ情報から取得され、codはJOINに必要な唯一のキーであるため、title、cod、visibleでインデックスを作成する場合( WHERE)の場合、物理テーブルにはまったくアクセスされない可能性があります。

これが2番目の式でも起こるかどうかはわかりません。

于 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

  • これはブール列である必要があるため、 WHEREp.visible = 't'をに簡略化 しました。p.visible

于 2012-07-09T20:48:24.850 に答える
1

サブクエリを使用します。テーブルエイリアスを忘れないでくださいtLIMITの後に来る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 に答える