web-dev-qa-db-fra.com

Existe-t-il un moyen de scinder les résultats d’une requête de sélection en deux parties égales?

J'ai besoin d'une solution pour une requête de sélection dans SQL Server 2005.

J'aimerais qu'une requête retourne deux ensembles de résultats dont chacun contient exactement la moitié des enregistrements correspondant à certains critères. J'ai essayé d'utiliser TOP 50% en conjonction avec un ordre de, mais si le nombre d'enregistrements dans la table est impair, un enregistrement apparaîtra dans les deux ensembles de résultats. Je ne veux pas qu'un enregistrement soit dupliqué sur les jeux d'enregistrements. Exemple:

J'ai une table simple avec les champs TheID (PK) et TheValue (varchar (10)) et 5 enregistrements. Passer la clause where pour le moment.

SELECT TOP 50 PERCENT * FROM TheTable ORDER BY TheID asc

résultats dans l'id sélectionné 1,2,3

SELECT TOP 50 PERCENT * FROM TheTable ORDER BY TheID desc

résultats dans l'id sélectionné 3,4,5

3 est un dup. Dans la vraie vie, bien sûr, les requêtes sont assez compliquées avec une tonne de clauses where et subqueries.

16
Mats

SQL Server 2005 et similaire:

select *, ntile(2) over(order by theid) as tile_nr from thetable

ntile(n) alloue la sortie en n segments de la même taille (arrondis ou non lorsque le nombre de lignes n'est pas divisible par n) Donc, cela produit la sortie:

1 | value1 | 1
2 | value2 | 1
3 | value3 | 1
4 | value4 | 2
5 | value5 | 2

Si vous voulez seulement la moitié supérieure ou inférieure, vous devez l'insérer dans une sous-requête, par exemple:

select theid, thevalue from (
  select theid, thevalue, ntile(2) over(order by theid) as tile_nr from thetable
) x
where x.tile_nr = 1

retournera la moitié supérieure, et utilisera de même x.tile_nr = 2 pour la moitié inférieure

40
araqnid

Vous pouvez utiliser ces deux requêtes:

SELECT * FROM (
    SELECT *, ROW_NUMBER() OVER (ORDER BY TheID) AS rn FROM TheTable
) T1
WHERE rn % 2 = 0

SELECT * FROM (
    SELECT *, ROW_NUMBER() OVER (ORDER BY TheID) AS rn FROM TheTable
) T1
WHERE rn % 2 = 1
7
Mark Byers

S'il s'agit de SQL Server 2000, alors je serais enclin à trouver le PK de la valeur moyenne comme suit

Declare @MiddleId int

Set @MiddleId = (
                Select TOP 1 PK
                From (
                        Select TOP 50 PERCENT PK
                        From Table
                        Order By TheId ASC
                        )
                Order By TheId DESC
                )

Select ...
From Table
Where TheId <= @MiddleId

Select ..
From Table
Where TheId > @MiddleId

Avec SQL Server 2005, je serais enclin à faire de même, mais vous pouvez utiliser un CTE

;With NumProjects As
    (
    Select Id, ROW_NUMBER() OVER (ORDER BY TheId ASC ) As Num
    From Table
    )
Select @MiddleId = Id
From Table
Where Num = CEILING( (Select Count(*) From Table) / 2 )
2
Thomas

essaye ça:

DECLARE @CountOf int,@Top int,@Bottom int
SELECT @CountOf=COUNT(*) FROM YourTable
SET @Top=@CountOf/2
SET @Bottom=@CountOf-@Top
SELECT TOP (@Top) * FROM YourTable ORDER BY 1 asc --assumes column 1 is your PK
SELECT TOP (@Bottom) * FROM YourTable ORDER BY 1 desc --assumes column 1 is your PK
1
KM.

Voici une autre solution:

Vous devez utiliser une table temporaire pour contenir les 50% premiers comme ci-dessous:

select top 50 percent * 
into #YourTempTable
from TheTable 

-- The below would give the first half
select * from #YourTempTable

-- The below woud give rest of the half 
select * from TheTable where TheID not in (select TheID from #YourTempTable)
0
Unbound