Новая помощь с оператором выбора SQL Server - PullRequest
0 голосов
/ 06 июня 2010

Мне нужна помощь с оператором выбора в SQL Server / T-SQL

Мой стол выглядит так:

Id (int)  
QuestionId (int)  
GenreId (int)  
QuestionScore (int)

Я хочу выбрать случайные N строк из этой таблицы, чтобы максимальное число одного и того же GenreId в наборе результатов было меньше X для всех GenreId-ов, кроме одного. Для этого GenreId мне нужно, чтобы количество строк с этим GenreId было равно Y .

UPDATE
Я составил этот запрос из предложений ниже, он работает именно так, как я хотел (за исключением одного жанра, но это не проблема, пусть будет так, у меня будет 2 запроса)

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
. Как я могу это сделать? мне нужны все столбцы, возвращенные в наборе результатов.
заранее спасибо:)

Ответы [ 2 ]

1 голос
/ 06 июня 2010

Для SQL Server 2005+ используйте:

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 голосов
/ 06 июня 2010

В SQL Server это можно сделать с помощью вложенных подзапросов и предложений 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...