2012-05-11 75 views
2

我有兩個兩個表questionpoolquestion其中question是多對一的question pool。我創建了一個查詢使用子選擇查詢返回正確的隨機結果,但我需要返回question表中的多個列。SQL Server:轉換子選擇查詢加入

查詢的目的是從「問題池」表中爲每個「QuizID」的'問題'表返回一個隨機測試。

SELECT QuestionPool.QuestionPoolID, 
(
SELECT TOP (1) Question.QuestionPoolID 
FROM Question 
WHERE Question.GroupID = QuestionPool.QuestionPoolID 
ORDER BY NEWID() 
) 
FROM QuestionPool 
WHERE QuestionPool.QuizID = '5' 

回答

3

OUTER APPLY適合此:

Select * 
FROM QuestionPool 
OUTER APPLY 
(
    SELECT TOP 1 * 
    FROM Question 
    WHERE Question.GroupID = QuestionPool.QuestionPoolID 
    ORDER BY NEWID() 
) x 
WHERE QuestionPool.QuizID = '5' 

OUTER的另一個例子APPLY使用http://www.ienablemuch.com/2012/04/outer-apply-walkthrough.html


現場測試:http://www.sqlfiddle.com/#!3/d8afc/1

create table m(i int, o varchar(10)); 
insert into m values 
(1,'alpha'),(2,'beta'),(3,'delta'); 

create table x(i int, j varchar, k varchar(10)); 

insert into x values 
(1,'a','hello'), 
(1,'b','howdy'), 
(2,'x','great'), 
(2,'y','super'), 
(3,'i','uber'), 
(3,'j','neat'), 
(3,'a','nice'); 


select m.*, '' as sep, r.* 
from m 
outer apply 
(
    select top 1 * 
    from x 
    where i = m.i 
    order by newid() 
) r 
+0

'xxx APPLY'的大粉絲,但它使您的查詢更便攜。 –

+1

@ ta.speot.is如果可移植性是項目最重要的關注點,那麼最好找到一種更便攜的替代方法。但是,挖掘數據庫潛力是最實用的方法,特別是如果它比便攜式的更快,例如HTTP:// explainextended。com/2009/07/16/inner-join-vs-cross-apply /畢竟,你爲此付出了代價,不妨使用與你購買的產品相關的產品特性,並使你的工作效率更高 –

0

不熟悉SQL服務器,但我希望這會做:

Select QuestionPool.QuestionPoolID, v.QuestionPoolID, v.xxx -- etc 
FROM QuestionPool 
JOIN 
     (
     SELECT TOP (1) * 
     FROM  Question 
     WHERE Question.GroupID = QuestionPool.QuestionPoolID 
     ORDER BY NEWID() 
     ) AS v ON v.QuestionPoolID = QuestionPool.QuestionPoolID 
WHERE QuestionPool.QuizID = '5' 
0

您的查詢似乎帶回任意Question.QuestionPoolId每個QuestionPool.QuestionPoolId受QuizId過濾器。

我認爲以下查詢做到這一點:

select qp.QuestionPoolId, max(q.QuestionPoolId) as any_QuestionPoolId 
from Question q join 
    qp.QuestionPoolId qp 
    on q.GroupId = qp.QuestionPoolId 
WHERE QuestionPool.QuizID = '5' 
group by qp.QuestionPoolId 

這將返回一個特定的問題。

下面的查詢將讓你得到更多的領域:

select qp.QuestionPoolId, q.* 
from (select q.*, row_number() over (partition by GroupId order by (select NULL)) as randrownum 
     from Question q 
    ) join 
    (select qp.QuestionPoolId, max(QuetionPool qp 
    on q.GroupId = qp.QuestionPoolId 
WHERE QuestionPool.QuizID = '5' and 
     randrownum = 1 

它使用ROW_NUMBER()來任意枚舉行。 「選擇NULL」提供了隨機排序(或者,你可以使用「通過的GroupId秩序」。

+1

你肯定'ORDER BY SELECT NULL' [我沒能得到那個工作(http://sqlfiddle.com/#!3/d41d8/ 1017)雖然'ORDER BY NEWID()'工作正常 –

+0

我會想象'ORDER BY NULL'提供* undefined *排序,但實際上它最終會按照使用哪個索引來讀取數據的大概順序非羣集或羣集)。從堆中讀取將導致按照插入順序排序。並行查詢計劃會產生不同的結果,但順序通常會如上所述。 –

+0

嗯,我在SQL Server 2008 R2中使用了「order by(select null)」。至於效果,排序是不確定的。在多線程環境中,情況更是如此。當然,newid()也可以。但是,這似乎是不必要的工作。在這種情況下,我只需要按「groupid」排序,因爲這應該提供未定義的排序。 SQL排序不穩定,這意味着它們不保留表中相同鍵的原始排序。 –