识别SQL Server 2014中的行模式

问题描述 投票:1回答:5

我有一个特殊的情况,我得到一些类似于以下内容的行,这来自于我无法控制的某些集成操作。

请使用此脚本进行复制

CREATE TABLE #SOMETABLE 
(
  FIELD VARCHAR,
  VALUE INT
)

INSERT INTO #SOMETABLE
(FIELD,VALUE)
VALUES
('A',1),
('B',3),
('C',5),

('A',90),
('B',15),
('C',21),

('A',31),
('B',75),
('C',82)

SELECT * FROM #SOMETABLE

您会得到

enter image description here

如您所见,A-B-C模式会重复其自身,并保证按此顺序重复,因此我需要使用额外的计算列(GROUP)来标识这些行的“组”。

所以它必须像这样结束

enter image description here

[我尝试过几次la脚的尝试,搜索过google,在这里和那里阅读文章,但我什至不知道Google搜索要使用什么术语,it does seem that SQL Server can identify patterns in rows,但我不确定从哪里开始

所以我的问题是:如何在SQL Server 2014中标识行组?

编辑

很难详细说明,但我可以说这里有一个唯一的ID字段,并且有一个“位置”字段可以保证所有ABC的顺序

CREATE TABLE #SOMETABLE 
(
ID INT IDENTITY(1,1) PRIMARY KEY,
 FK_FIELD_NAME VARCHAR,
 [VALUE] INT,
 [FK_FIELD_POSITION] INT
)

INSERT INTO #SOMETABLE
(ID,FK_FIELD_NAME,[VALUE],[FK_FIELD_POSITION])
VALUES
(1,'A',1,17),
(2,'B',3,18),
(3,'C',5,19),

(4,'A',90,17),
(5,'B',15,18),
(6,'C',21,19),

(7,'A',31,17),
(8,'B',75,18),
(9,'C',82,19)

SELECT * FROM #SOMETABLE

enter image description here

sql sql-server sql-server-2014
5个回答
2
投票

尝试一下:

在添加到临时表之前,向该表和VOILA添加一个自动增量:

DROP TABLE #SOMETABLE
CREATE TABLE #SOMETABLE 
(
ID int NOT NULL IDENTITY(1,1),
 FIELD VARCHAR,
 VALUE INT
)

INSERT INTO #SOMETABLE
(    FIELD,VALUE)
VALUES
('A',1),
('B',3),
('C',5),

('A',90),
('B',15),
('C',21),

('A',31),
('B',75),
('C',82)

SELECT *, ceiling(ID/3.0) FROM #SOMETABLE

1
投票

可能是最简单,最简单的方法是使用游标在行上进行迭代:

create table #sometable2
(
    field varchar,
    [value] int,
    [group] int
)

declare @field char(1)
declare @value int
declare @group int = 1

declare something_cursor cursor for 
select field, [value] from #sometable

open something_cursor  
fetch next from something_cursor into @field, @value 

while @@fetch_status = 0  
begin  
      insert into #sometable2 select @field, @value, @group 

      if @field = 'C' set @group = (select @group + 1)

      fetch next from something_cursor into @field, @value
end 

close something_cursor  
deallocate something_cursor

select * from #sometable2

结果:

╔═══════╤═══════╤═══════╗
║ field │ value │ group ║
╠═══════╪═══════╪═══════╣
║ A     │ 1     │ 1     ║
╟───────┼───────┼───────╢
║ B     │ 3     │ 1     ║
╟───────┼───────┼───────╢
║ C     │ 5     │ 1     ║
╟───────┼───────┼───────╢
║ A     │ 90    │ 2     ║
╟───────┼───────┼───────╢
║ B     │ 15    │ 2     ║
╟───────┼───────┼───────╢
║ C     │ 21    │ 2     ║
╟───────┼───────┼───────╢
║ A     │ 31    │ 3     ║
╟───────┼───────┼───────╢
║ B     │ 75    │ 3     ║
╟───────┼───────┼───────╢
║ C     │ 82    │ 3     ║
╚═══════╧═══════╧═══════╝

1
投票

您是否可以添加另一个ID列?也许还有ROW_NUMBER()窗口函数。

CREATE TABLE #SOMETABLE 
(
 ID INT,
 FIELD VARCHAR,
 VALUE INT
)

INSERT INTO #SOMETABLE
(ID,FIELD,VALUE)
VALUES
(1,'A',1),
(2,'B',3),
(3,'C',5),

(4,'A',90),
(5,'B',15),
(6,'C',21),

(7,'A',31),
(8,'B',75),
(9,'C',82)

SELECT t.*
     , ROW_NUMBER() OVER(PARTITION BY t.ID % 3 ORDER BY t.ID) rn
FROM #SOMETABLE t
ORDER BY t.ID

或者如果您无法添加ID字段...我不保证:

SELECT t2.*
     , ROW_NUMBER() OVER(PARTITION BY t2.ID % 3 ORDER BY t2.ID) rn
FROM(
     SELECT t.*, ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) ID
     FROM #SOMETABLE t
    )t2
ORDER BY t2.ID

1
投票

解决该问题的合理通用方法是按照FK_FIELD_POSITION的顺序计算(ID,FK_FIELD_POSITION)减少的次数。

EG

drop table if exists #SOMETABLE
go
CREATE TABLE #SOMETABLE 
(
ID INT  PRIMARY KEY,
 FK_FIELD_NAME VARCHAR,
 [VALUE] INT,
 [FK_FIELD_POSITION] INT
)

INSERT INTO #SOMETABLE
(ID,FK_FIELD_NAME,[VALUE],[FK_FIELD_POSITION])
VALUES
(1,'A',1,17),
(2,'B',3,18),
(3,'C',5,19),

(4,'A',90,17),
(5,'B',15,18),
(6,'C',21,19),

(7,'A',31,17),
(8,'B',75,18),
(9,'C',82,19);

with q as
(
SELECT *, case when fk_field_position < LAG(fk_field_position) over (order by id,fk_field_position) then 1 else 0  end groupStart
FROM #SOMETABLE
)
select *, 1+sum(groupStart) over (order by id) groupNum
from q

输出

ID          FK_FIELD_NAME VALUE       FK_FIELD_POSITION groupStart  groupNum
----------- ------------- ----------- ----------------- ----------- -----------
1           A             1           17                0           1
2           B             3           18                0           1
3           C             5           19                0           1
4           A             90          17                1           2
5           B             15          18                0           2
6           C             21          19                0           2
7           A             31          17                1           3
8           B             75          18                0           3
9           C             82          19                0           3

(9 rows affected)

1
投票

这里是一种将'A'视为意甲中的第一个方法。然后将相同的等级分配给非'A'。

这也意味着,如果跟随'D'或'E'或其他非'A'的方法,此方法仍然有效。

CREATE TABLE #SOMETABLE 
(
 ID INT IDENTITY(1,1) PRIMARY KEY,
 FIELD VARCHAR(30),
 VALUE INT
);
INSERT INTO #SOMETABLE
(FIELD,VALUE)
VALUES
('A',1), ('B',3), ('C',5),
('A',90),('B',15),('C',21),
('A',31),('B',75),('C',82);
GO
9行受影响
SELECT *
, SUM(CASE WHEN FIELD='A' THEN 1 ELSE 0 END) 
    OVER (ORDER BY ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS Rnk
FROM #SOMETABLE
ORDER BY ID
GO
ID |领域|值|排行-:| :---- | ----:| -:1 | A | 1 | 1个2 | B | 3 | 1个3 | C | 5 | 1个4 | A | 90 | 25 | B | 15 | 26 | C | 21 | 27 | A | 31 | 38 | B | 75 | 39 | C | 82 | 3

db <>小提琴here

© www.soinside.com 2019 - 2024. All rights reserved.