2011-01-19 3 views
5

Предположим, у вас есть таблица, как (я использую SQL Server 2008, не журнал аудита - таблица огромна):Выберите строки, где цена не изменились

SecID | Date | Price 
1  1/1/11  10 
1  1/2/11  10 
1  1/3/11  5 
1  1/4/11  10 
1  1/5/11  10 

Пусть эта таблица ОГРОМНЫЕ (миллионы строк для различные secIDs и дата) - Я хотел бы вернуться записи, когда цена изменилась (искать что-то лучше, чем с помощью курсора и итерация):

Am пытается выяснить, как получить:

SecID | StartDate | EndDate | Price 
1  1/1/11  1/2/11 10 
1  1/3/11  1/3/11 5 
1  1/4/11  1/5/11 10 

то есть другой способ взглянуть на это - это то, что я ищу диапазон дат, где цена осталась прежней.

+0

В какой базе данных вы используете? – Oded

+0

У вас есть эта информация, хранящаяся в другой таблице (т. Е. Журнал аудита)? –

+1

Непонятно, что вы хотите - это набор записей, определяющих диапазон дат, для которых цена осталась прежней? –

ответ

8

Это «острова» проблема.

declare @Yourtable table 
(SecID int, Date Date, Price int) 

INSERT INTO @Yourtable 
SELECT 1,GETDATE()-5,10 union all 
SELECT 1,GETDATE()-4,10 union all 
SELECT 1,GETDATE()-3,5 union all 
SELECT 1,GETDATE()-2,10 union all 
SELECT 1,GETDATE()-1, 10 

;WITH cte AS 
(
SELECT SecID,Date,Price, 
     ROW_NUMBER() OVER (PARTITION BY SecID ORDER BY Date) - 
     ROW_NUMBER() OVER (PARTITION BY Price, SecID ORDER BY Date) AS Grp 
FROM @Yourtable 
) 
SELECT SecID,Price, MIN(Date) StartDate, MAX(Date) EndDate 
FROM cte 
GROUP BY SecID, Grp, Price 
ORDER BY SecID, MIN(Date) 
+0

На самом деле, этот ответ лучше, чем у меня :) –

+0

это выглядит хорошо! – Denis

+0

+1 это здорово! –

0

Я думаю, что это должно работать

SELECT SecID, Min(Date) AS StartDate, Max(Date) AS EndDate, Price FROM BigTable GROUP BY SecID, EndDate Having Min(Date) != MAx(Date) And Date != NULL 
+0

Это не сработает, потому что в строке 2 моего примера Min (Date) = Max (Date) и последняя строка будут отброшены (так как цена = 10 уже найдена в первой строке). Хорошая попытка - подумал об этом один на некоторое время. (BTW, дата отмечена как «NOT NULL») – Denis

+0

вы также должны группироваться по цене, а не по EndDate. В любом случае, если вы замените это и вытащите 'HAVING', он должен работать нормально – Lamak

+1

Это не сработает, потому что если вы группируете по SecID, Price, то у вас будут (1, 10) и (1, 5), поэтому 2 строки только в вашем результирующем наборе. У вас должны быть 3: (1, 10), (1, 5) и (1,10) снова. – Denis

2

Если значение не изменяется, то отклонение станда будет нулевой

select secId 
    from ... 
group by secId 
having count(*) = 1 
    OR stdev(price) = 0 
+0

+1 Это умно, мне интересно, насколько результативен stddev? – Matthew

+0

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

 Смежные вопросы

  • Нет связанных вопросов^_^