Есть ли способ разделить результаты запроса выбора на две равные половины?

Мне нужно решение для запроса select в Sql Server 2005.

Я хотел бы получить запрос, возвращающий два ResultSets, каждый из которых содержит ровно половину всех записей, соответствующих определенным критериям. Я попытался использовать TOP 50 PERCENT в сочетании с Order By, но если количество записей в таблице нечетное, одна запись будет отображаться в обоих наборах результатов. Я не хочу, чтобы какая-либо запись дублировалась по наборам записей. Пример:

У меня есть простая таблица с полями TheID (PK) и TheValue (varchar (10)) и 5 ​​записей. Пропустите предложение where на данный момент.

SELECT TOP 50 PERCENT * FROM TheTable ORDER BY TheID asc

приводит к выбранному id 1,2,3

SELECT TOP 50 PERCENT * FROM TheTable ORDER BY TheID desc

приводит к выбранному id 3,4,5

3 - это dup. В реальной жизни, конечно, запросы довольно сложны с тонной частью предложений и подзапросов.

Ответ 1

SQL Server 2005 и аналогичные:

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

ntile(n) выделяет выходные данные в n сегментов, каждый из которых имеет одинаковый размер (дайте или округлите, когда количество строк не делится на n). Таким образом, получается выход:

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

Если вам просто нужна верхняя или нижняя половина, вам нужно поместить это в подзапрос, например:

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

вернет верхнюю половину и аналогичным образом использует x.tile_nr = 2 для нижней половины

Ответ 2

Вы можете использовать эти два запроса:

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

Ответ 3

Если это SQL Server 2000, я был бы склонен найти PK среднего значения следующим образом:

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

С SQL Server 2005 я был бы склонен делать то же самое, но вы можете использовать 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 )

Ответ 4

попробуйте следующее:

DECLARE @CountOf int,@Top int,@Bottom int
SELECT @CountOf=COUNT(*) FROM YourTable
SET @[email protected]/2
SET @[email protected]@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

Ответ 5

Это запрос, который я нашел полезным (после изменений курса):

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

DECLARE @countRecords float SET @countRecords = (Выберите COUNT (*) From sz_hold_visitsData) - Excel может хранить одновременно записи за один миллион. если @countRecords >= 1000000 SET @numberofitemsperpage = 500000 ELSE IF @countRecords < 1000000 И @countRecords >= 500000 SET @numberofitemsperpage = 250000 ELSE IF @countRecords < 500000 И @countRecords >= 100000 SET @numberofitemsperpage = 50000 ELSE SET @numberofitemsperpage = 10000

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

SET @numberofpages = ПОТОЛОК (@numberofpages_deci) Выберите @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) WHERE ROW >= @currentpage * @numberofitemsperpage +1 И Row <= (@currentpage + 1) * @numberofitemsperpage

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

В этом выводе "sz_hold_visitsData" - это таблица в моей базе данных, в то время как "person_ID" - это столбец. Вы также можете дополнительно модифицировать script для вывода в файл:

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

DECLARE @countRecords float SET @countRecords = (Выберите COUNT (*) From sz_hold_visitsData) - Excel может хранить одновременно записи за один миллион. если @countRecords >= 1000000 SET @numberofitemsperpage = 500000 ELSE IF @countRecords < 1000000 И @countRecords >= 500000 SET @numberofitemsperpage = 250000 ELSE IF @countRecords < 500000 И @countRecords >= 100000 SET @numberofitemsperpage = 50000 ELSE SET @numberofitemsperpage = 10000

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

SET @numberofpages = ПОТОЛОК (@numberofpages_deci) Выберите @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 НАЧАТЬ --SELECT a. * FROM (SELECT row_number() OVER (ORDER BY person_ID) AS ROW, * FROM sz_hold_visitsData) WHERE ROW >= @currentpage * @numberofitemsperpage +1 И Row <= (@currentpage + 1) * @numberofitemsperpage SET @outputFile = 'C:\PSM\outVisits_' + convert (nvarchar (50), @currentpage) + '.csv' --Выбрать @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) WHERE ROW >= '+ CONVERT (nvarchar (500), @текущая страница * @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

Надежда помогает.

Ответ 6

Вот еще одно решение:

Вам нужно будет использовать временную таблицу для хранения первых 50%, как показано ниже:

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)