Разделить выходные строки по группам в SQL Server - PullRequest
2 голосов
/ 18 ноября 2009

Я должен разделить строки поровну, так вот, например, есть 15 строк. Я хочу разделить поровну, который состоит из трех групп, но я хочу, чтобы имя приходило только перед первым элементом каждой группы, как показано:

DECLARE @NAMES TABLE
(
[ID] INT IDENTITY,
[NAME] VARCHAR(20)
)


INSERT INTO @NAMES
SELECT 'NAME1' UNION ALL
SELECT 'NAME2' UNION ALL
SELECT 'NAME3' UNION ALL
SELECT 'NAME4' UNION ALL
SELECT 'NAME5' UNION ALL
SELECT 'NAME6' UNION ALL
SELECT 'NAME7' UNION ALL
SELECT 'NAME8' UNION ALL
SELECT 'NAME9' UNION ALL
SELECT 'NAME10' UNION ALL
SELECT 'NAME11' UNION ALL
SELECT 'NAME12' UNION ALL
SELECT 'NAME13' UNION ALL
SELECT 'NAME14' UNION ALL
SELECT 'NAME15' 

Желаемый вывод:

ID          NAME
----------- --------------------
1           NAME1
2           
3           
4           
5           
6           NAME6
7           
8           
9           
10          
11          NAME11
12          
13          
14    
15

Ответы [ 3 ]

7 голосов
/ 18 ноября 2009

Если вы используете SQL 2005 или более позднюю версию, для любого числа строк следует выполнить следующие действия:

declare @numBuckets;
select @numBuckets = 3;

;with nameBase as
(
    select  ntile(@numBuckets) over(order by ID) as bucket,
            NAME, ID
    from    @NAMES
),
nameRows as
(
    select  row_number() over(partition by bucket order by ID) as rn,
            NAME, ID
    from    nameBase

)
select  n.ID, case when rn = 1 then n.NAME else null end as NAME
from    nameRows n
order by ID;

Если вам нужно решение для SQL 2000 или ANSI, попробуйте следующее:

declare @numRecs int, @numBuckets int, @recsPerBucket int;
select @numRecs = count(*) from @NAMES;
select @numBuckets = 3;
select @recsPerBucket = @numRecs / @numBuckets;

select  n.ID, case when d1.minIdInBucket is null then null else n.NAME end as NAME
from    @NAMES n
left join (
            select  min(n2.ID) as minIdInBucket
            from    (
                        select  n1.ID, n1.NAME,
                                (
                                    select  count(*) / @recsPerBucket
                                    from    @NAMES n2
                                    where   n2.ID < n1.ID
                                ) as bucket
                        from    @NAMES n1
                    ) n2
            group by n2.bucket
        ) d1
on      n.ID = d1.minIdInBucket
order by n.ID;
0 голосов
/ 18 ноября 2009

Вы можете рассчитать номер строки и общее количество строк в подзапросе. Внешний выбор может затем выбрать на основе этих столбцов:

select 
    id,
    case 
        when id = 1 then name 
        when id = total/3+1 then name 
        when id = total*2/3+1 then name 
        else '' 
    end
from (
    select row_number() over (order by id) as nr,
        (select count(*) from @names) as total,
        *
    from @names
) sub
0 голосов
/ 18 ноября 2009
SELECT ID, CASE WHEN (ID = 1 OR ID = 6 OR ID = 11) THEN Name Else NULL END
FROM @Names

Я знаю, что это глупый способ сделать это.
Но гораздо лучше написать его таким образом для ограниченного набора строк (согласно вашему примеру).

Если у вас есть больше строк (чем 15), пожалуйста, напишите.
Я постараюсь выяснить, могу ли я вывести формулу, чтобы результаты можно было распечатать в соответствии с вашими ожиданиями.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...