Функция для обнаружения изменений в упорядоченном списке - PullRequest
2 голосов
/ 29 декабря 2010

Я хотел бы найти решение в 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  |
|---------|-------|-----|

Ответы [ 2 ]

4 голосов
/ 29 декабря 2010

Предполагается, что 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
0 голосов
/ 29 декабря 2010

Это может быть немного изменено, чтобы работать. Кроме того, я никогда не использую циклы, сделать это, возможно, не самый эффективный способ сделать это.

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

Ну, так или иначе, это общая идея ...

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