2012-05-19 3 views
2

그래서 재미있는 문제가 생겼습니다. 나는 쉬운 해결책이있을 것이라고 확신하지만 그것이 무엇인지는 잘 모르겠습니다. :)MySQL GROUP BY rand()?

기본적으로

, 그래서 같이 아주 간단한 데이터베이스를 상상 :

---------------- 
T1 
---------------- 
    r | nID 
--------------- 
    1 | A 
    2 | B 
---------------- 




---------------- 
T2 
---------------- 
nID | val 
--------------- 
    A | XXX 
    B | L 
    B | M 
    B | N 
    B | P 
---------------- 

는 기본적으로, 표 2 참조 이제 표 1, 나는 그러나 A 또는 B 중 하나에서 임의의 행을 선택하고 싶습니다 우선 A와 B를 랜덤 화하고 싶다면 관련 값을 선택하십시오.

즉, 동전을 뒤집기 : 머리, XXX. 꼬리, L, M, N, 또는 P.

내 현재 쿼리가 RAND(), 다음에 LIMIT 1의 두 테이블을 조인합니다. 그러나, 이것은 A 값이 선택 될 확률보다 B 값의 가능성이 훨씬 더 많이 선택되도록합니다. 저는 PHP를 사용하기 때문에 두 개의 쿼리를 쉽게 실행할 수 있습니다. 그러나 하나의 쿼리를 실행하는 것이 훨씬 더 정돈되어 있으므로 여러분이 추천하는 것을보고 싶습니다.

모든 솔루션? =)

편집 :

여기에 내 현재 쿼리하지만이 작동하지 않습니다. 왜 그런지!

SELECT * 
FROM t2 
WHERE 
    nID = 
    (
     SELECT nID 
     FROM t1 
     ORDER BY RAND() 
     LIMIT 1 
    ) 
ORDER BY RAND() 
LIMIT 1 

편집 2 :

나는 데 문제를 설명하기 위해 테스트 케이스를 만들었습니다.

T1 and T2

내가 L, M, N, 또는 P을 선택하는 동일한 것으로 XXX를 선택하는 확률을하려면 첫째, 나는 다음과 같은 테이블을 만들었습니다. 내가 가지고있는 질의가 그것을해야한다, 그렇지? 그래서 나는 그것을 시험했다. 다음 스크립트는 쿼리를 5000 번 실행하고 결과를 계산합니다. 그들은 약 50-50이어야하며 XXX은 약 2500 번, 그 외 모든 것은 약 2500 번 나타납니다.

XXX - 937 
Other - 4063 

은 이제 다시 실행하자

$a = 0; 
$b = 0; 
$i = 0; 
while ($i < 5000) 
{ 
    $query = mysql_query(" 
     SELECT * 
     FROM t2 
     WHERE 
      nID = 
      (
       SELECT nID 
       FROM t1 
       ORDER BY RAND() 
       LIMIT 1 
      ) 
     ORDER BY RAND() 
     LIMIT 1 
     ") or die(mysql_error()); 

    $result = mysql_fetch_array($query); 
    if ($result['val'] == 'XXX') 
    { 
     $a++; 
    } 
    else 
    { 
     $b++; 
    } 

    $i++; 
} 

echo "XXX - $a<br />"; 
echo "Other - $b<br />"; 

다음은 결과입니다.

XXX - 968 
Other - 4032 

그리고 한 번 더 실행 해 봅시다.

XXX - 932 
Other - 4068 

이것은 내 쿼리에서 볼 때 거의 50-50으로 나뉩니다. 지구상에서 무슨 일이야? 도와 줘서 고마워!

+0

PHP에서 mt_rand를 사용하여 랜덤 화를 시도 할 수 있습니까? 그것을 더 나은 무작위 값을 줄 수 있다고 가정? – sree

+0

전적으로 MySQL에서 이것을하고 싶습니다. 결과의 불균형 분포는 B 값보다 A 값이 적기 때문입니다. – Nathanael

+0

시연 할 테스트 케이스를 실행했습니다. 위 참조.^ – Nathanael

답변

2

질문에있는 하위 쿼리가 외부 쿼리 당 한 번 실행될 것으로 예상되지만, 그렇지 않은 것처럼 보입니다. 나는 아래 당신이있어 무엇을 줄 수도 생각 후 :

SET @randID = (SELECT nID 
FROM T1 
ORDER BY RAND() 
LIMIT 1); 

SELECT VAL 
FROM T2 
WHERE nID = @randID 
ORDER BY RAND() 
LIMIT 1; 

(SQL Fiddle)

당신이하면, 당신이 필요 A 또는 B 선택하려는 경우
+0

요아킴 이삭손 (Joachim Isaksson)의 솔루션은 논증 할 수있을 정도로 우아하지만 실제로이 솔루션을 더 좋아합니다. J.I.는 덜 직관적 인 반면, 한눈에 이해하는 것이 더 쉽습니다. 도와 줘서 고마워! – Nathanael

1

시도하십시오 쿼리는 내가 그래서 당신의 테이블 구조에 따라 필드 이름을 사용하십시오 두 테이블에 대한 열 이름 필드 1과 FIELD2 가정 여기

SELECT `table2`.* FROM `table2` WHERE table2.field1 = (Select table1.field2 from table1 order by RAND() limit 0,1) LIMIT 0,1 

아래에 주어진.

감사

+0

수정 된 쿼리보기 여전히 작동하지 않는 것 같습니다. :/ – Nathanael

+0

이 솔루션이 작동하지 않았지만 올바른 길로 나를 도왔습니다. 감사! – Nathanael

0
SELECT 
    CASE rq.r WHEN '1' THEN t1q.r ELSE t2q.nID END AS Col1, 
    CASE rq.r WHEN '1' THEN t1q.nID ELSE t2q.val END AS Col2 
FROM 
    (SELECT CASE WHEN RAND() < 0.5 THEN '1' ELSE '2' END AS r) AS rq 
    JOIN (SELECT * FROM T1 ORDER BY RAND() LIMIT 1) as t1q 
    JOIN (SELECT * FROM T2 ORDER BY RAND() LIMIT 1) as t2q 

관측 : 그것은 단지 하나를 사용하더라도 두 테이블에서 임의의 행을 선택이 필요하기 때문에이 쿼리가 비효율적이다. 아마도 더 좋은 방법이있을 것입니다.

+2

이 쿼리를 이해할 수 없어서 현재 구현하고있는 방법으로 구현하는 방법을 모르겠습니다. 당신은 설명 할 수 있고 아마도 위의 예제와 일치하도록 테이블/컬럼 이름을 수정할 수 있습니까? – Nathanael

2

귀하의 예를 내부 쿼리는 여러 번 평가 그것을 다시 작성하십시오 (예 : JOIN). 당신은 작은 테이블과 함께 작업하는 경우

SELECT q2.nID, q2.val 
FROM (SELECT nID FROM T1 ORDER BY RAND() LIMIT 1) q1 
JOIN T2 q2 ON q1.nID = q2.nID 
ORDER BY RAND() 
LIMIT 1 

,이 쿼리는 확인 될 수 있지만, 큰 테이블에 대한 ORDER BY RAND()을 사용하지 말아야하는 이유에 here for example을 읽어야합니다.

데모 here.