2011-11-24 1 views
2

유일하지 않은 (반복되지 않는) 값의 열에서 다른 임의 값의 이전에 선택되지 않은 쌍을 선택하는 가장 효율적인 방법은 무엇입니까? ?mysql 최적화 : 고유 값 열에서 다른 값의 이전에 선택되지 않은 임의의 쌍을 선택하십시오.

내 현재의 접근 방식은 (이미 별도의 "mytable_associations"테이블에 관련된 값의 모든 쌍을 유지)된다

SELECT * FROM 
(
SELECT id,count(*) AS associations_count FROM mytable 
INNER JOIN mytable_associations 
WHERE (myvalue=myvalue1 OR myvalue=myvalue2) 
GROUP BY myvalue 
HAVING associations_count<(SELECT count(*) FROM mytable)-1 
ORDER BY rand() limit 1 
) mytable1 
LEFT JOIN 
(SELECT myvalue AS myvalue2 FROM mytable) mytable2 
ON mytable1.myvalue1<>mytable2.myvalue2 
WHERE 
(
SELECT myvalue1 FROM mytable_associations 
WHERE 
myvalue1=mytable1.myvalue1 AND myvalue2=mytable2.myvalue2 
OR 
myvalue1=mytable2.myvalue2 AND myvalue2=mytable1.myvalue1 
) IS NULL; 

(그리고 물론 업데이트 mytable_associations을이 새로운 협회)

어떤, 보시다시피 일부 최적화를 통해 큰 이익을 얻을 수 있습니다.

(코드의 빈 들여 쓰기에 대해 미안하지만, 나는 정말로 mysql 명령을 들여 쓰는 방법을 모른다.)

나를 도와 줄 수 있습니까?

(PS이 이제까지 여기에 게시 내 첫 번째 질문입니다 : 내가 잘못 일을 많이하고 있어요 내가 필연적 flamming을 이해하고 싶지만, 나 너무 열심히하지 마세요 물론;))

+0

검색어를 이해하는 것이 약간 까다로운 것으로 보입니다. 질의의 다른 부분을 설명하고 그들이하는 일과 같은 몇 가지 통찰력을 주시겠습니까? – Abhay

+0

기본적으로 두 부분으로 이루어지기를 원하는 바를 모범 사례로 제시 할 수 있다면 좋을 것입니다. 먼저 다른 모든 것과 결합되지 않은 값을 선택합니다. SELECT RANDOM FROM mytable WHERE (associations_table의 각 값에 대한 연관 수 선택) <(mytable에서 선택 개수 (*)) -1. 그 것이 확실하다면 나머지는 associations_table에 이미 연관되어 있지 않은 다른 값을 선택하는 것입니다. 마지막 두 WHERE 절이있는 것입니다. – NotGaeL

+0

은 코드를 덜 복잡하게 만들도록 업데이트했습니다. 희망이 지금은 더 읽을 수 있지만, 어쨌든 빌 Karwin에서 솔루션을 보면, 내가 뭘 찾고 있었는지 – NotGaeL

답변

2

order by rand()과 관련된 모든 솔루션은 비효율적입니다. 대안은 다음을 참조하십시오

Selecting random rows with MySQL에 이미 포착 한 숫자를 제외하려면, 여기에 내가 (이 의사입니다)을 할 거라고 방법은 다음과 같습니다

$c1 = SELECT COUNT(DISTINCT myvalue) FROM mytable 
$c2 = SELECT COUNT(*) FROM mytable_associations 

$offset = ROUND(RAND() * ($c1 * ($c1-1) - $c2)) 

SELECT v.* FROM (
    SELECT LEAST(m1.myvalue,my2.myvalue) AS myvalue1, 
    GREATEST(m1.myvalue,my2.myvalue) AS myvalue2 
    FROM (SELECT DISTINCT myvalue FROM mytable) AS m1 
    INNER JOIN (SELECT DISTINCT myvalue FROM mytable) AS m2 
    ON m1.myvalue <> m2.myvalue 
) AS v 
LEFT OUTER JOIN mytable_associations AS a USING (myvalue1,myvalue2) 
WHERE a.myvalue1 IS NULL 
LIMIT 1 OFFSET $offset 

myvalue1 < myvalue2를 보장하고 mytable_associations에 순서대로 저장하면 결합을 단순화 할 수 있습니다.

+0

rand()에 의한 주문을 사용하지 않는 것은 확실히 개선되었지만 포인트 3에 대해서는 어떻게 볼 수 없는가? .myvalue1 IS NULL "은 (a, b)를 선택하고 (b, a)를 선택하는 것을 피하고, 실행하려고하면 알 수없는 열 myvalue1을 말합니다. (시도한 a.myvalue1 및 mytable_associations.myvalue1도 구문 오류로 변환). 이를 방지하기 위해 두 조합을 연관 테이블에 추가해야합니까? 이 오류로 이어지는 솔루션을 실행하려고하면 무엇을 잘못 할 수 있습니까? – NotGaeL

+0

(BTW, 답장을 보내 주셔서 대단히 감사합니다. SQL로 시작하고 때로는 올바르게 처리하는 방법을 파악하기가 어려워집니다.) – NotGaeL

+0

사과, 원래 질문에서 오해가 있습니다. 오해했습니다. 귀하의 테이블 구조. 나는 내 대답을 다시 썼다. –

관련 문제