2010-06-05 2 views
0

/T-SQL새로운 도움을 내가 SQL Server의 SELECT 문에 도움이 필요

내 표는 다음과 같습니다

내가 N 행에서 무작위로 선택합니다
Id (int) 
QuestionId (int) 
GenreId (int) 
QuestionScore (int) 

이 테이블은 결과 집합에서 동일한 GenreId의 최대 수가 X보다 작고 모든 GenreId-s가 하나가되도록합니다. 해당 GenreId의 경우 해당 GenreId와 행 수가 Y이되어야합니다.

나는 아래의 제안에서이 쿼리를 만들어
UPDATE, 그것은 내가 원하는대로 정확하게 작동

select top @N * from 
(select Id,GenreId,Rank() over (Partition BY GenreId order by newId()) as Rank,QuestionScore from Questions) t 
where t.Rank <= @X 
order by newId() 
(하나 개의 장르를 제외하고 있지만 문제를 이잖아, 그것은 이런 식으로하자, 병은이 개 질문이)

지금 평균 QuestionScore가 1.7과 2.3 사이가되도록 행을 선택해야합니다.
어떻게하면됩니까? 결과 집합에서 반환 된 모든 열이 필요합니다. SQL 서버 2005 +, 사용하기 위해 미리 :)

+2

일반적으로 귀하의 요청은 불가능한 것 같습니다. N이 100이고 X가 5이고 장르가 두 개라면? 어떤 가정을하고 있습니까? 그리고 이것이 얼마나 무작위 적인가? 다양한 장르를 얻는 것이 더 중요합니까? 결과에 한 장르가 완전히 나타나지 않으면 괜찮습니까? –

+1

사용중인 SQL Server의 버전을 확인하는 데 도움이됩니다. –

+0

SQL Server 2005를 사용하고 있습니다. N의 최대 값은 33이고 장르의 수는 ~ 50입니다. 일부 장르가 결과에 포함되지 않으면 확인됩니다. –

답변

1

에서
감사 :

SQL 서버에서
SELECT TOP (@n) c.* 
    FROM (
SELECT a.id, 
     a.questionid, 
     a.genreid 
    FROM (SELECT t.*, 
       ROW_NUMBER() OVER (PARTITION BY t.genreid) AS rank 
      FROM TABLE t 
     WHERE t.genreid NOT IN (SELECT TOP 1 --ensure only one genre, see order by 
             t.genreid 
            FROM TABLE t 
           GROUP BY t.genreid 
           HAVING COUNT(*) = @y 
           ORDER BY t.genreid) 
    ) a 
WHERE a.rank < @x 
UNION ALL 
SELECT b.id, 
     b.questionid, 
     b.genreid 
    FROM TABLE b 
WHERE b.genreid IN (SELECT TOP 1 --ensure only one genre, see order by 
          t.genreid 
         FROM TABLE t 
        GROUP BY t.genreid 
        HAVING COUNT(*) = @y 
        ORDER BY t.genreid)) c 
+0

@y는 특정 genere에 대한 다른 제한이라고 생각합니다. 장르를 찾는 데 사용되지 않아야합니다. 그럴 경우 더 많은 것을 발견 할 수 있습니다. – Andomar

+0

@Andomar : OP에서 집합에서 제외 된 genreid에 행 수가 * y *가되어야한다고 명시되어 있습니다. * y * 행 수의 genreid가 두 개 이상있을 가능성이 매우 높습니다. TOP에서는 중복 항목 중 어떤 것이 선택 될지 더 많이 알았을 때이를 처리 할 것입니다. –

+0

많이 고마워요 :) –

0

, 당신이 할 수있는 중첩 된 하위 쿼리 및 top 조항과 :

select top (@n) * 
from (
     -- Retrieve @y rows from the special genre 
     -- The prio field is used to ensure all these rows make it inside @n 
     select top (@y) 1 as prio, genreid, questionid 
     from @t 
     where genreid = @the_one 

     -- And up to @x rows per non-special genre 
     union all 
     select 2 as prio, genreid, questionid 
     from (
       select * 
       ,  row_number() over (partition by genreid 
              order by newid()) as rownr 
       from @t 
       where genreid <> @the_one 
       ) sub 
     where rownr < @x 
     ) sub2 
order by 
     prio, newid() 

샘플 데이터 :

declare @t table (id int identity, QuestionId int, GenreId int) 

insert @t (GenreId, QuestionId) values 
    (1,1), 
    (2,1),(2,1), 
    (3,1),(3,1),(3,1), 
    (4,1),(4,1),(4,1),(4,1), 
    (5,1),(5,1),(5,1),(5,1),(5,1) 

declare @n int 
declare @x int 
declare @y int 
declare @the_one int 

set @n = 7 -- Total rows 
set @x = 3 -- With less then 3 per genre 
set @y = 3 -- Except three rows from genre @the_one 
set @the_one = 3 

각 실행마다 출력이 달라집니다.

prio genreid questionid 
1  3  1 
1  3  3 
1  3  2 
2  4  1 
2  1  1 
2  5  1 
2  5  4 
+0

고맙습니다 :) –

관련 문제