запрос - из группы строк должно остаться одно значение с указанным статусом

Matroz
Дата: 22.01.2009 10:13:38
Есть таблица StatusChanges (Status int, ChangeTime datetime),
значения: status 0 или 1, ChangeTime - время изменения статуса.
Если отсортировать по ChangeTime, то получаем группы строк
с неизменным статусом.
Вместо каждой группы нужно оставить одну строку с минимальным временем

Решение вроде бы где-то рядом, но пока сделал с помощью цикла.

сервер - MS SQL 2000
Гавриленко Сергей Алексеевич
Дата: 22.01.2009 10:18:14
select Status, Min(ChangeTime)
from StatusChanges 
group by Status
Matroz
Дата: 22.01.2009 10:39:36
select Status, Min(ChangeTime)
from StatusChanges
group by Status

нее, здесь останется всего 2 записи.
А нужно из
1  2009-01-19 12:00:00
1  2009-01-19 12:05:00
1  2009-01-19 12:09:00
1  2009-01-19 12:31:00

0  2009-01-19 12:40:00
0  2009-01-19 12:54:00
0  2009-01-19 13:01:00

1  2009-01-19 14:02:00
1  2009-01-19 14:25:00
1  2009-01-19 14:40:00

получить

1  2009-01-19 12:00:00

0  2009-01-19 12:40:00

1  2009-01-19 14:02:00
Glory
Дата: 22.01.2009 10:40:54
Т.е. Status + ChangeTime являются ПК ?
aleks2
Дата: 22.01.2009 10:41:05
Matroz
Есть таблица StatusChanges (Status int, ChangeTime datetime),
значения: status 0 или 1, ChangeTime - время изменения статуса.
Если отсортировать по ChangeTime, то получаем группы строк
с неизменным статусом.
Вместо каждой группы нужно оставить одну строку с минимальным временем

Решение вроде бы где-то рядом, но пока сделал с помощью цикла.

сервер - MS SQL 2000


select T.*
from StatusChanges T
inner join
StatusChanges P
ON P.ChangeTime<T.ChangeTime AND P.Status<>T.Status
WHERE not exists(select * from StatusChanges X WHERE P.ChangeTime<X.ChangeTime AND X.ChangeTime<T.ChangeTime)
aleks2
Дата: 22.01.2009 10:48:22
И такие люди учат студентов MS SQL-ю... хе-хе... И шо потом со студента спросишь?
iap
Дата: 22.01.2009 10:58:48
SELECT [Status], MIN(ChangeTime) FROM\n(\n SELECT T.[Status], T.ChangeTime,\n (SELECT COUNT(*) FROM StatusChanges TT WHERE TT.ChangeTime<=T.ChangeTime)-\n (SELECT COUNT(*) FROM StatusChanges TT WHERE TT.[Status]=T.[Status] AND TT.ChangeTime<=T.ChangeTime)\n FROM StatusChanges T\n) TT([Status],ChangeTime,G)\nGROUP BY [Status],G\nORDER BY 2;
Кстати, недавено ссылку давали на похожую тему,
где была предложена сама идея: /topic/116495&hl=#902102
aleks2
Дата: 22.01.2009 11:01:19
Кстати, если париться за быстродействие, то

CREATE TABLE #tmp (
	[Status] [int] NOT NULL ,
	[ChangeTime] [datetime] NOT NULL ,
	[AnyWhat] [varchar] (50) COLLATE Cyrillic_General_CI_AS NULL 
) 

CREATE  UNIQUE  INDEX [IX_tmp] ON #tmp([ChangeTime],[Status]) WITH  IGNORE_DUP_KEY 

insert #tmp([ChangeTime],[Status],[AnyWhat])
select [ChangeTime],[Status],[AnyWhat]
FROM StatusChanges
ORDER BY [ChangeTime]

быстрее не сделать.
aleks2
Дата: 22.01.2009 11:05:44
aleks2
Кстати, если париться за быстродействие, то

CREATE TABLE #tmp (
	[Status] [int] NOT NULL ,
	[ChangeTime] [datetime] NOT NULL ,
	[AnyWhat] [varchar] (50) COLLATE Cyrillic_General_CI_AS NULL 
) 

CREATE  UNIQUE  INDEX [IX_tmp] ON #tmp([ChangeTime],[Status]) WITH  IGNORE_DUP_KEY 

insert #tmp([ChangeTime],[Status],[AnyWhat])
select [ChangeTime],[Status],[AnyWhat]
FROM StatusChanges
ORDER BY [ChangeTime]

быстрее не сделать.


Пардон... слегка поспешил с выводами.
Matroz
Дата: 22.01.2009 11:50:36
aleks2
И такие люди учат студентов MS SQL-ю... хе-хе... И шо потом со студента спросишь?

Дорогой Олег Евгеньевич, то что предложено вами далее, для меня не новость.
Такого рода решение у меня есть, есть также решение с помощью курсора и
решение с циклом, внутри которого запоминаются ChangeTime переходов.
Последнее на реальных данных (там изменений статуса немного) показывает
максимальное быстродействие. Интересны более изящные решения,
классические что-ли, без создания временных объектов и циклов.