2012-05-11 4 views
2

으로 변환합니다. questionpoolquestion이 있는데, questionquestion pool의 다수 대 1입니다. 올바른 임의 결과를 반환하는 하위 선택 쿼리를 사용하여 쿼리를 만들었지 만 question 테이블에서 둘 이상의 열을 반환해야합니다.SQL Server : 하위 선택 쿼리를

쿼리의 의도는 'Question Pool'테이블의 각 'QuizID'에 대한 'question'테이블에서 무작위 테스트를 반환하는 것입니다.

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' 

아우터의 또 다른 예는 이용 적용 http://www.ienablemuch.com/2012/04/outer-apply-walkthrough.html


,451,515,

라이브 테스트 : 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.co.kr/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

귀하의 쿼리는 QuizId 필터 각 QuestionPool.QuestionPoolId 대상에 대한 임의의 Question.QuestionPoolId을 다시 가져 오는 것으로 보인다.

나는 다음 쿼리는이 작업을 수행 생각 :

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"는 "그룹 ID에 의해 순서를"사용할 수있는 대안 (임의의 순서를 제공합니다.

+1

당신이 SELECT NULL' BY ORDER'에 대한 확신이 ([내가 그 일을 얻을 수 없습니다] http://sqlfiddle.com/#!3/d41d8/ 1017)'ORDER BY NEWID()'가 괜찮 았음에도 불구하고 –

+0

'ORDER BY NULL'은 * undefined * ordering을 제공한다고 생각 하겠지만 현실에서는 데이터를 읽는 데 사용되는 인덱스의 대략적인 순서로 끝날 것입니다 (비 클러스터 또는 클러스터). 힙을 읽으면 삽입 순서에 따라 순서가 지정됩니다. 병렬 질의 계획은 다른 결과를 산출하지만 순서는 일반적으로 위에서 설명한대로입니다. –

+0

흠, SQL Server 2008 R2에서 "order by (select null)"을 사용했습니다. 효과에 관해서는 순서가 정의되지 않습니다. 다중 스레드 환경에서는 이것이 더 많은 경우입니다. 물론 newid()도 작동합니다. 그러나 불필요한 작업처럼 보입니다. 나는이 경우에 "groupid에 의한 순서"로 간다. 정의되지 않은 순서를 제공해야하기 때문이다. SQL 정렬은 불안정합니다. 즉, 동일한 키에 대해 테이블의 원래 순서를 보존하지 않습니다. –