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

后端 未结 6 1631
无人及你
无人及你 2020-12-28 17:19

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 matchin

相关标签:
6条回答
  • 2020-12-28 17:42

    If this is SQL Server 2000, then I'd be inclined to find the PK of the middle value like so:

    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
    

    With SQL Server 2005, I'd be inclined to do the same but you can use a 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 )
    
    0 讨论(0)
  • 2020-12-28 17:47

    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

    0 讨论(0)
  • 2020-12-28 17:51

    You could use these two queries:

    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
    
    0 讨论(0)
  • 2020-12-28 17:59

    This is the query I found useful (after modifications of-course):

    DECLARE @numberofitemsperpage INT DECLARE @numberofpages INT DECLARE @currentpage int

    DECLARE @countRecords float SET @countRecords = (Select COUNT(*) From sz_hold_visitsData) -- the Excel can hold approximately ONE MILLION records at a time. if @countRecords >= 1000000 SET @numberofitemsperpage = 500000 ELSE IF @countRecords < 1000000 AND @countRecords >= 500000 SET @numberofitemsperpage = 250000 ELSE IF @countRecords < 500000 AND @countRecords >= 100000 SET @numberofitemsperpage = 50000 ELSE SET @numberofitemsperpage = 10000

    DECLARE @numberofpages_deci float SET @numberofpages_deci = @countRecords / @numberofitemsperpage

    SET @numberofpages = CEILING(@numberofpages_deci) Select @countRecords AS countRecords, @numberofitemsperpage AS numberofitemsperpage , @numberofpages_deci AS numberofpages_deci, @numberofpages AS numberofpagesFnl

    SET @currentpage =0 WHILE @currentpage < @numberofpages BEGIN SELECT a.* FROM (SELECT row_number() OVER (ORDER BY person_ID) AS ROW, * FROM sz_hold_visitsData) a WHERE ROW >= @currentpage * @numberofitemsperpage +1 AND Row <= (@currentpage+1) * @numberofitemsperpage

    IF @@ROWCOUNT = 0 BREAK SET @currentpage = @currentpage +1 END

    In this extract, "sz_hold_visitsData" is a table in my database, whilst "person_ID" is a column therein. You can also further modify the script to output to file:

    DECLARE @numberofitemsperpage INT DECLARE @numberofpages INT DECLARE @currentpage int

    DECLARE @countRecords float SET @countRecords = (Select COUNT(*) From sz_hold_visitsData) -- the Excel can hold approximately ONE MILLION records at a time. if @countRecords >= 1000000 SET @numberofitemsperpage = 500000 ELSE IF @countRecords < 1000000 AND @countRecords >= 500000 SET @numberofitemsperpage = 250000 ELSE IF @countRecords < 500000 AND @countRecords >= 100000 SET @numberofitemsperpage = 50000 ELSE SET @numberofitemsperpage = 10000

    DECLARE @numberofpages_deci float SET @numberofpages_deci = @countRecords / @numberofitemsperpage

    SET @numberofpages = CEILING(@numberofpages_deci) Select @countRecords AS countRecords, @numberofitemsperpage AS numberofitemsperpage , @numberofpages_deci AS numberofpages_deci, @numberofpages AS numberofpagesFnl

    DECLARE @sevrName nvarchar(50) SET @sevrName = '.\sql14' DECLARE @outputFile nvarchar(500)

    SET @currentpage =0 WHILE @currentpage < @numberofpages BEGIN --SELECT a.* FROM (SELECT row_number() OVER (ORDER BY person_ID) AS ROW, * FROM sz_hold_visitsData) a WHERE ROW >= @currentpage * @numberofitemsperpage +1 AND Row <= (@currentpage+1) * @numberofitemsperpage SET @outputFile = 'C:\PSM\outVisits_' +convert(nvarchar(50), @currentpage) + '.csv' --Select @outputFile --TEST

    DECLARE @cmd_ varchar(500) = 'sqlcmd -S ' + @sevrName + ' -E -Q "SELECT a.* FROM (SELECT row_number() OVER (ORDER BY person_ID) AS ROW, * FROM sz_hold_visitsData) a WHERE ROW >= '+ CONVERT(nvarchar(500),@currentpage * @numberofitemsperpage +1) +' AND Row <= ' + CONVERT(nvarchar(500),((@currentpage+1) * @numberofitemsperpage)) +'" -s "," -o ' +@outputFile +' ' -- "C:\PSM\outVisits.csv" ' EXEC xp_cmdshell @cmd_

    IF @@ROWCOUNT = 0 BREAK SET @currentpage = @currentpage +1 END

    Hope helps.

    0 讨论(0)
  • 2020-12-28 18:01

    try this:

    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
    
    0 讨论(0)
  • 2020-12-28 18:06

    Here is another solution:

    You would need to use a temp table to hold the first 50% as below:

    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 讨论(0)
提交回复
热议问题