2010-06-05 10 views
0

J'ai besoin d'aide avec instruction select dans SQL Server/T-SQLNouvelle aide avec instruction select SQL Server

Ma table ressemble à ceci:

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

Je veux choisir au hasard N lignes de cette table afin que le nombre maximum de même GenreId dans le jeu de résultats soit inférieur à X pour tous les GenreId-s sauf un. Pour ce GenreId, j'ai besoin que le nombre de lignes avec ce GenreId soit égal à Y.

MISE À JOUR
J'ai fait cette requête de suggestions ci-dessous, il fonctionne exactement comme je voulais (sauf pour un genre, mais c'est pas de problème, que ce soit de cette façon, malade ont 2 requêtes)

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() 

maintenant je dois sélectionner des lignes de sorte que QuestionScore moyen est entre 1.7 ET 2.3
comment puis-je faire cela? J'ai besoin de toutes les colonnes retournées dans le jeu de résultats.
merci à l'avance :)

+2

Votre requête semble généralement impossible. Et si N est 100, X est 5 et il n'y a que 2 genres? Quelles hypothèses faites-vous? Et comment cela devrait-il être aléatoire? Est-il plus important d'avoir beaucoup de genres différents? Est-ce OK si un genre est complètement non représenté dans les résultats. –

+1

Il serait utile de connaître la version de SQL Server que vous utilisez. –

+0

Im en utilisant SQL Server 2005. La valeur maximale de N est de 33 et le nombre de Genres est ~ 50 Il est correct si certains genres ne seront pas inclus dans le résultat. –

Répondre

1

Pour SQL Server 2005+, utilisez:

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

Je pense que @y est une limite différente pour un genre spécifique, ce n'est pas censé être utilisé pour trouver un genre. Si tel était le cas, il pourrait en trouver plus d'un, en contradiction avec la question – Andomar

+0

@Andomar: L'OP indique que le genre de genre exclu de l'ensemble doit avoir un nombre de lignes de * y *. Il est très probable qu'il pourrait y avoir plus d'un genreid avec * y * nombre de lignes - TOP gérerait cela une fois que nous en saurions plus sur lequel des doublons serait sélectionné. –

+0

Merci beaucoup :) –

0

Dans SQL Server, vous pouvez le faire avec les sous-requêtes imbriquées et top clauses:

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() 

données d'échantillon :

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 

Résultats en (un examen la sortie diffère à chaque fois:

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

Merci beaucoup :) –

Questions connexes