Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to split the results of a select query into two equal halfs?

I need a solution for a select query in Sql Server 2005.

I'd like to have a query returning two ResultSets each of which holding exactly half of all records matching a certain criteria. I tried using TOP 50 PERCENT in conjunction with an Order By but if the number of records in the table is odd, one record will show up in both resultsets. I don't want to have any record duplicated over the recordsets. Example:

I've got a simple table with TheID (PK) and TheValue fields (varchar(10)) and 5 records. Skip the where clause for now.

SELECT TOP 50 PERCENT * FROM TheTable ORDER BY TheID asc

results in the selected id's 1,2,3

SELECT TOP 50 PERCENT * FROM TheTable ORDER BY TheID desc

results in the selected id's 3,4,5

3 is a dup. In real life of course the queries are fairly complicated with a ton of where clauses and subqueries.

like image 461
Mats Avatar asked May 05 '10 19:05

Mats


People also ask

How do you subtract two SELECT statements in SQL Server?

The Minus Operator in SQL is used with two SELECT statements. The MINUS operator is used to subtract the result set obtained by first SELECT query from the result set obtained by second SELECT query.

How do you divide query output into a group?

How To Divide Query Output into Groups? You can divide query output into multiple groups with the GROUP BY clause. It allows you specify a column as the grouping criteria, so that rows with the same value in the column will be considered as a single group.


1 Answers

SQL Server 2005 and similar:

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

ntile(n) allocates the output into n segments, each of the same size (give or take rounding when the number of rows isn't divisible by n). So this produces the output:

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

If you just want the top or bottom half, you need to put this into a subquery, e.g.:

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

will return the top half, and similarly use x.tile_nr = 2 for the bottom half

like image 73
araqnid Avatar answered Oct 22 '22 12:10

araqnid