2011-01-27 166 views
3

我有兩個表像這樣:如何從表中隨機選擇唯一的行對?

CREATE TABLE people (
    id INT NOT NULL, 
    PRIMARY KEY (id) 
) 

CREATE TABLE pairs (
    person_a_id INT, 
    person_b_id INT, 
    FOREIGN KEY (person_a_id) REFERENCES people(id), 
    FOREIGN KEY (person_b_id) REFERENCES people(id) 
) 

我想從百姓餐桌隨機選擇對的人,選擇它們後,我加入隨機選擇對的對錶。 person_a_id始終是指對中較低的id的人(因爲該對的順序不相關)。

的事情是,我從來沒有想選擇同一對兩次,所以我需要檢查對錶之前,我回我隨機選擇的對。

是否有可能做到這一點在一個合理的高效和優雅的方式使用只是一個單一的SQL查詢?

(我這樣做是使用Java Persistence API,但希望我能翻譯任何答案爲JPA代碼)

+0

這可能是可行的,但它不會很漂亮。 – Matchu 2011-01-27 23:34:31

+0

我不明白這是如何在基於集合的方法中可能的。我可以使用遊標來解決它(因此可以在單個存儲過程中完成)。最大的障礙是您的選擇池必須減少您添加到對錶中的每個隨機對。 – Matthew 2011-01-27 23:37:02

回答

4
select a.id, b.id 
from people1 a 
inner join people1 b on a.id < b.id 
where not exists (
    select * 
    from pairs1 c 
    where c.person_a_id = a.id 
     and c.person_b_id = b.id) 
order by a.id * rand() 
limit 1; 

Limit 1回報只是一對,如果你是「抽籤」一次一個。否則,儘可能多的限制,你需要。

上面的查詢假設你可以得到

1 - 2 
2 - 7 

和配對2 - 7是有效的,因爲它不存在,即使2登場亮相。如果你只想要一個人來推薦only one對不斷,然後

select a.id, b.id 
from people1 a 
inner join people1 b on a.id < b.id 
where not exists (
    select * 
    from pairs1 c 
    where c.person_a_id in (a.id, b.id)) 
    and not exists (
    select * 
    from pairs1 c 
    where c.person_b_id in (a.id, b.id)) 
order by a.id * rand() 
limit 1; 

如果multiple pairs是在一個單一的查詢中產生,目標表仍然是空的,你可以使用這個單號查詢。請注意,LIMIT 6只返回3對。

select min(a) a, min(b) b 
from 
(
    select 
     case when mod(@p,2) = 1 then id end a, 
     case when mod(@p,2) = 0 then id end b, 
     @p:[email protected]+1 grp 
    from (
     select id 
     from (select @p:=1) p, people1 
     order by rand() 
     limit 6 
    ) x 
) y 
group by floor(grp/2) 
1

這不可能在一個單一的查詢來完成基於集合的方法,因爲你設置將不知道哪些對插入到對錶中。

相反,你應該循環

WHILE EXISTS(SELECT * FROM people 
    WHERE id NOT IN (SELECT person_a_id FROM pairs) 
    AND id NOT IN (SELECT person_b_id FROM pairs) 

這將循環,同時還有無與倫比的人。 那麼你應該從1到表 它給你無與倫比的人數的CNT(*)兩個隨機數...如果你得到了相同的號碼,再滾動。 (如果你擔心這個,隨機從集合的兩半數字......但那麼你就失去了根據您的排序標準的一些隨機性)

對那些人。

洗滌,沖洗,重複...... 當您生成相同的隨機數兩次時,您唯一的「重做」將更容易,因爲您只有幾個人但仍然只有25%的機會優於1/N^2)