在SQL Server中拆分组中的输出行

时间:2009-11-18 14:17:29

标签: sql sql-server

我必须平均划分行, 所以在这里,例如,有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 个答案:

答案 0 :(得分:7)

如果您使用的是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;

答案 1 :(得分:0)

SELECT ID, CASE WHEN (ID = 1 OR ID = 6 OR ID = 11) THEN Name Else NULL END
FROM @Names

我知道这是一种愚蠢的做法 但是,以这种方式为有限的行集编写它更好(根据您的示例)。

如果您有更多行数(超过15个),请发布。
我会试着看看我是否能得出一个公式,以便按照你的期望打印出结果。

答案 2 :(得分:0)

您可以计算子查询中的行号和总行数。然后外部选择可以根据这些列进行选择:

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