我喜欢在T-SQL中找到可以找到检测给定列表或记录中的更改的方法的解决方案。
物理表是这样的:
| id |val |
|----|----|
| 1 | A |
|----|----|
| 2 | A |
|----|----|
| 3 | B |
|----|----|
| 4 | B |
|----|----|
| 5 | A |
|----|----|
| 6 | A |
|----|----|
id
是一个顺序整数
val
是一个任意值
我想添加一个计算字段,可以某种方式表示val
期望的结果:
| id |val | segment |
|----|----|---------|
| 1 | A | 1 |
|----|----|---------|
| 2 | A | 1 |
|----|----|---------|
| 3 | B | 2 |
|----|----|---------|
| 4 | B | 2 |
|----|----|---------|
| 5 | A | 3 |
|----|----|---------|
| 6 | A | 3 |
|----|----|---------|
我想要做的是按照这样的“细分”进行分组的可能性:
| from_id | to_id | val |
|---------|-------|-----|
| 1 | 2 | A |
| 3 | 4 | B |
| 5 | 6 | A |
|---------|-------|-----|
答案 0 :(得分:4)
假设SQL Server 2005 +
DECLARE @T TABLE (
id INT PRIMARY KEY,
val CHAR(1))
INSERT INTO @T
SELECT 1,'A' UNION ALL SELECT 2,'A' UNION ALL
SELECT 3,'B' UNION ALL SELECT 4,'B' UNION ALL
SELECT 5,'A' UNION ALL SELECT 6,'A'
;WITH cte1 AS(
SELECT
id,
val,
ROW_NUMBER() OVER (ORDER BY id) - ROW_NUMBER() OVER (PARTITION BY val ORDER BY id) AS Grp
FROM @T
),
cte2 AS(
SELECT
id,
val,
MIN(id) OVER (PARTITION BY Grp, val) AS GrpStart
FROM cte1
)
SELECT
id,
val,
DENSE_RANK() OVER (ORDER BY GrpStart) AS segment
FROM cte2
或更新的要求更简单
;WITH cte AS(
SELECT
id,
val,
ROW_NUMBER() OVER (ORDER BY id) - ROW_NUMBER() OVER (PARTITION BY val ORDER BY id) AS Grp
FROM @T
)
SELECT
val,
MIN(id) AS from_id,
MAX(id) AS to_id
FROM cte
GROUP BY Grp, val
ORDER BY from_id
答案 1 :(得分:0)
这可能需要稍微修改才能工作。此外,我从不使用循环,这可能不是最有效的方法。
Declare @counter int
Set @counter = 1
Declare @seg int
Set @seg = 1
Declare @cur varchar(50)
Set @ cur = select val from table where id = 1
While @counter <= select max id from table
Begin
if(@cur == select val from table where id = @counter)
update table set segment = @seg where id = @counter
else
{
set @cur = select val from table where id = @counter
set @ seg = @seg + 1
update table set segment = @seg where id = @counter
}
Set @counter = @counter + 1
End
那就是一般的想法......