0

次のようなクエリがあります。

SELECT tb1.id, tb2.id 
FROM tb1
JOIN tb2 ON tb1.group = tb2.id
WHERE 
tb1.status = 1 AND tb2.status = 1
GROUP BY tb1.group
ORDER BY RAND( ) 
LIMIT 2

どちらのテーブルも小さい (1000 行未満) ため、ORDER BY RAND() は問題ありません。

tb2 の各レコードに対して、tb1 には 10 個のレコードがあります (tb2.id = tb1.group によってリンクされています)。各グループの tb1 にランダムなレコードがある 2 つの異なるグループを選択したいと思います。

GROUP BY 句を使用すると、常にグループ内の最初のレコードが tb1 から選択されます。GROUP BY 句を削除すると、ランダムなものが選択されます....しかし、同じグループ内の2つのアイテムが時々選択される可能性があります。

2 つの異なるグループで、tb1 から 2 つのランダムなレコードを選択するにはどうすればよいですか?

4

2 に答える 2

1

どういうわけか、これは私が思っているよりも複雑に思えますが、要件を満たしていると思います:

select tb2.*,
       (select tb1.id from tb1 where tb1.group = tb2.id and tb1.status = 1 order by rand() limit 1) 
from tb2
where tb2.status = 1 and
      exists (select 1 from tb1 where tb1.status = 1 and tb1.group = tb2.id)
group by tb2.id
order by rand()
limit 2
于 2013-02-05T03:21:43.063 に答える
0

私はあなたが求めているものを誤解しているかもしれません. したがって、tb2 に 100 のレコードがある場合、結果セットには 200 が必要です... グループ #1 に 2、グループ #2 に 2、グループ #3 に 2 など.

もしそうなら、私はあなたのクエリをラップしてMySQL変数を利用し、グループごとにカウンターを置き、HAVING句を適用します...

select
      AllPossible.group,
      @lastSeq := if( AllPossible.group = @lastGroup, @lastSeq +1, 1 ) as GroupSeq,
      @lastGroup = AllPossible.group
   from
      ( SELECT 
              tb1.id, 
              tb2.id 
           FROM 
              tb1
                 JOIN tb2
                    ON tb1.group = tb2.id
           WHERE 
                  tb1.status = 1 
              AND tb2.status = 1
           ORDER BY 
              tb1.group,
              RAND( ) ) AllPossible,
      ( select @lastGroup := 0,
               @lastSeq := 0 ) sqlvars
   having
      GroupSeq < 3;

前クエリ (別名 "AllPossible" ) は、両方のテーブルから結合された一意の修飾された status=1 レコードを引き続き取得します...ただし、最初に同じグループの順序ですべてを配置し、次にランダムに配置します。

グループ レコード グループ シーケンス

1     19      1     (keep)
1     95      2     (keep)
1     3       3     (throw away)
1     28      4     (throw away)

2     34      1     (keep)
2     14      2     (keep)
2     89      3     (throw away)
2     41      4     (throw away)

3     9       1     (keep)
3     25      2     (keep)
3     42      3     (throw away)
3     76      4     (throw away)

そこから順番に「グループシーケンス」を割り当てます。RAND() が最初に適用され、ランダムな順序で返されるため、レコード 1、2、3、4、(次のグループ)、つまり 1、2、3、4 などをスタンプするだけです。グループ シーケンスが 3 未満のもののみが必要なため、グループごとに 1 と 2 のみを保持し、最終結果セットから残りをすべて破棄します。

于 2013-02-05T03:52:58.090 に答える