给出这个表和数据:
DECLARE @Table table (RowID int, RowCode char(1), RowValue int);set nocount on
INSERT @Table VALUES ( 6,'A',3757 )
INSERT @Table VALUES ( 5,'A',37827)
INSERT @Table VALUES (14,'A',48411)
INSERT @Table VALUES ( 1,'A',48386)
INSERT @Table VALUES (20,'A',48450)
INSERT @Table VALUES ( 7,'A',46155)
INSERT @Table VALUES (13,'A',721 )
INSERT @Table VALUES ( 2,'A',49335)
INSERT @Table VALUES (15,'A',4700 )
INSERT @Table VALUES (19,'A',64416)
INSERT @Table VALUES ( 8,'A',27246)
INSERT @Table VALUES (12,'B',54929)
INSERT @Table VALUES (16,'B',3872 )
INSERT @Table VALUES ( 3,'C',728 )
INSERT @Table VALUES (11,'C',1050 )
INSERT @Table VALUES ( 9,'C',3191 )
INSERT @Table VALUES (17,'C',866 )
INSERT @Table VALUES ( 4,'C',838 )
INSERT @Table VALUES (10,'D',550 )
INSERT @Table VALUES (18,'D',1434 );set nocount off
我需要这个:
VVVVVVVV
RowID RowCode RowValue RowChunk
----- ------- -------- --------
1 A 48386 1
2 A 49335 1
5 A 37827 1
6 A 3757 1
7 A 46155 1
8 A 27246 2
13 A 721 2
14 A 48411 2
15 A 4700 2
19 A 64416 2
20 A 48450 3
12 B 54929 4
16 B 3872 4
3 C 728 5
4 C 838 5
9 C 3191 5
11 C 1050 5
17 C 866 5
10 D 550 6
18 D 1434 6
RowChunk从1开始,每次RowCode更改时增加1和/或有5个相同的RowCode值。
答案 0 :(得分:2)
基本上我的解决方案使用与您相同的方法,只使用稍微不同的设备。
WITH NumberedRows AS (
SELECT
RowID,
RowCode,
RowValue,
CodeChunk = (ROW_NUMBER() OVER (PARTITION BY RowCode ORDER BY RowID) - 1) / 5
FROM @Table
)
SELECT
RowID,
RowCode,
RowValue,
RowChunk = DENSE_RANK() OVER (ORDER BY RowCode, CodeChunk)
FROM NumberedRows
答案 1 :(得分:0)
我认为没有分析功能或任何合理的组合,这将解决这个问题。你必须用光标做RBAR,或者我的经验稍微快一点。
此循环示例假定RowID是唯一的。如果RowID不是集群PK,那么这将非常慢,所以如果是这种情况,你将需要创建一个临时表。
DECLARE @RowID INT = (SELECT MIN(RowID) FROM @Table)
DECLARE @MaxRowID INT = (SELECT MAX(RowID) FROM @Table)
DECLARE @RowCode CHAR(1)
DECLARE @LastRowCode CHAR(1)
DECLARE @RowValue INT
DECLARE @Chunk INT = 0
DECLARE @RecsThisChunk INT
DECLARE @Results TABLE (RowID INT NOT NULL PRIMARY KEY, RowCode CHAR(1) NOT NULL, RowValue INT NOT NULL, Chunk INT NOT NULL)
WHILE @RowID <= @MaxRowID
BEGIN
-- Handle gaps in RowID
IF NOT EXISTS (SELECT * FROM @Table WHERE RowID = @RowID) GOTO EndOfLoop
-- Load values for this record
SELECT @RowCode = RowCode, @RowValue = RowValue FROM @Table WHERE RowID = @RowID
IF @LastRowCode IS NULL OR @RowCode <> @LastRowCode OR @RecsThisChunk = 5
BEGIN
-- Start a new chunk
SET @Chunk = @Chunk + 1
SET @RecsThisChunk = 1
END
ELSE
BEGIN
-- Same chunk
SET @RecsThisChunk = @RecsThisChunk + 1
END
SET @LastRowCode = @RowCode
INSERT INTO @Results (RowID, RowCode, RowValue, Chunk) VALUES (@RowID, @RowCode, @RowValue, @Chunk)
EndOfLoop:
SET @RowID = @RowID + 1
END
SELECT * FROM @Results
您可能会在2005年对此进行一些调整,我会定期使用2008并且不记得所有的小差异。
仅供参考,您显示的结果与样本数据不完全匹配。
希望这有帮助!我看到的唯一选择是游标,或在应用程序层中处理它。
答案 2 :(得分:0)
这是您正在寻找的答案:
create Table [table] (RowID int, RowCode char(1), RowValue int)
INSERT [Table] VALUES ( 6,'A',3757 )
INSERT [Table] VALUES ( 5,'A',37827)
INSERT [Table] VALUES (14,'A',48411)
INSERT [Table] VALUES ( 1,'A',48386)
INSERT [Table] VALUES (20,'A',48450)
INSERT [Table] VALUES ( 7,'A',46155)
INSERT [Table] VALUES (13,'A',721 )
INSERT [Table] VALUES ( 2,'A',49335)
INSERT [Table] VALUES (15,'A',4700 )
INSERT [Table] VALUES (19,'A',64416)
INSERT [Table] VALUES ( 8,'A',27246)
INSERT [Table] VALUES (12,'B',54929)
INSERT [Table] VALUES (16,'B',3872 )
INSERT [Table] VALUES ( 3,'C',728 )
INSERT [Table] VALUES (11,'C',1050 )
INSERT [Table] VALUES ( 9,'C',3191 )
INSERT [Table] VALUES (17,'C',866 )
INSERT [Table] VALUES ( 4,'C',838 )
INSERT [Table] VALUES (10,'D',550 )
INSERT [Table] VALUES (18,'D',1434 )
IF object_id('tempdb..#tempTable') IS NOT NULL
BEGIN
DROP TABLE #tempTable
END
CREATE TABLE #tempTable
(RowID int, RowCode char(1), RowValue int,RowChunk int)
INSERT INTO #tempTable
select RowID,RowCode,RowValue,null from [table]
declare @RowId int
declare @RowCode char(1)
declare @Count int
declare @CurrentCode char(1)
declare @CountCurrent int
set @Count=1
set @CurrentCode=1
set @CountCurrent=0
DECLARE contact_cursor CURSOR FOR
SELECT RowID,RowCode FROM [table]
OPEN contact_cursor
FETCH NEXT FROM contact_cursor into @RowId,@RowCode
set @CurrentCode=@RowCode
WHILE @@FETCH_STATUS = 0
BEGIN
if(@CurrentCode=@RowCode)
begin
if(@CountCurrent=5)
begin
set @CountCurrent=1
set @Count=@Count+1
update #tempTable set RowChunk=@Count where RowID=@RowID
end
else
begin
set @CountCurrent=@CountCurrent+1
update #tempTable set RowChunk=@Count where RowID=@RowID
end
end
else
begin
set @CurrentCode=@RowCode
set @CountCurrent=1
set @Count=@Count+1
update #tempTable set RowChunk=@Count where RowID=@RowID
end
FETCH NEXT FROM contact_cursor into @RowId,@RowCode
END
CLOSE contact_cursor
DEALLOCATE contact_cursor
select * from #tempTable
GO
答案 3 :(得分:0)
这没有循环的技巧:
;WITH NumberedRows AS (
SELECT
r.RowID, r.RowCode, r.RowValue, CEILING(ROW_NUMBER() OVER(PARTITION BY r.RowCode ORDER BY r.RowCode,r.RowID)/5.0) AS CodeRowChunk
FROM @Table r
)
, AllChunks AS (
SELECT r.*,ROW_NUMBER() OVER(ORDER BY RowCode,CodeRowChunk) AS ChunkRowNumber
FROM (SELECT DISTINCT
RowCode, CodeRowChunk
FROM NumberedRows) r
)
SELECT
a.RowID, RowCode, a.RowValue,
(SELECT ChunkRowNumber FROM AllChunks c WHERE c.RowCode=a.RowCode and c.CodeRowChunk=a.CodeRowChunk) AS RowChunk
FROM NumberedRows a