2014-11-12 4 views
1

У меня возникли проблемы с поиском запроса для отображения только последовательных дат (минимум 3) в SQL. После поиска обмена стеками есть несколько решений, но я не могу заставить их работать именно так, как я этого хочу. Рассмотрим следующую таблицу (фактические данные и имена таблиц изменены в целях безопасности):Найти все последовательные даты в SQL

code   food   date 
------  ------  ------ 
ABC123  Sushi  09/28/2013 
ABC123  Sushi  09/29/2013 
ABC123  Sushi  09/30/2013 
ABC123  Sushi  10/01/2013 
BCD234  Burger  10/05/2013 
BCD234  Burger  10/10/2013 
BCD234  Burger  10/27/2013 
BCD234  Fries  10/05/2013 
BCD234  Fries  10/06/2013 
BCD234  Fries  10/10/2013 
CDE345  Steak  10/15/2013 
CDE345  Steak  10/16/2013 
CDE345  Steak  10/17/2013 
CDE345  Steak  10/19/2013 
CDE345  Steak  10/20/2013 
DEF456  Pasta  09/05/2013 
DEF456  Pasta  09/06/2013 
DEF456  Pasta  09/10/2013 
DEF456  Burrito  09/09/2013 
DEF456  Burrito  09/10/2013 
DEF456  Burrito  09/11/2013 

Только это должно быть отображено:

code   food   date 
------  ------  ------ 
ABC123  Sushi  09/28/2013 
ABC123  Sushi  09/29/2013 
ABC123  Sushi  09/30/2013 
ABC123  Sushi  10/01/2013 
CDE345  Steak  10/15/2013 
CDE345  Steak  10/16/2013 
CDE345  Steak  10/17/2013 
DEF456  Burrito  09/09/2013 
DEF456  Burrito  09/10/2013 
DEF456  Burrito  09/11/2013 

Учитывая, что код, продукты питания, дата и все переменной в любой данный время, какой будет запрос для создания результата, как показано выше? Запрос должен найти только минимум 3 последовательных дат для каждого заданного кода и пары продуктов (ключ).

Я пытался возиться с одним из запросов на Stack Exchange Server:

select code, grp, count(*) as NumInSequence, min(date), max(date) 
from (select t.*, (date - row_number() over (partition by code order by date)) as grp 
    from #TempTable t 
    ) t 
group by code, grp 

... но я получаю ошибку о преобразовании типов данных VARCHAR в BigInt (что, вероятно, связано с кодом является алфавитно-цифровых против простого регулярного идентификатора int). Кроме того, я предполагаю, что приведенный выше код не даст мне точного результата.

Просьба проконсультироваться и поблагодарить вас за помощь.

+0

Хм, может быть, я сегодня замедлился, но не ясно, как вы от первой таблицы до второй (более сжатой) таблицы – Coffee

+0

ах это 'минимум 3 последовательных дат для каждого заданного кода и пары продуктов (ключ)' – Coffee

ответ

3

Вы можете сделать это, используя функции окна. Вы можете определить группы последовательных дат, вычитая row_number() с даты. С группой, вы можете подсчитать количество строк, и выбрать только те, которые имеют 3 или более строк:

select code, food, date 
from (select t.*, count(*) over (partition by code, food, grp) as cnt 
     from (select t.*, 
        dateadd(day, - row_number() over (partition by code, food order by date), date) as grp 
      from #temptable t 
      ) t 
    ) t 
where cnt >= 3; 
+0

Спасибо за ваш ответ. Однако я проверил это, и результаты оказались пустыми. – misosouper

+0

Это может произойти, если, например, ваши даты имели компоненты времени. Можете ли вы настроить SQL Fiddle? –

+0

http://sqlfiddle.com/#!3/acf0d/3 – misosouper

0
you can create temp table with two additional columns 
    columns-id (identify(1,1) and delta_date. 
    and insert into it the 'old table'. 
    the column 'delta_date' is results of date(column2)-date(column1) by day 
    (and so for all rows respectively). 
    now you can select all rows where 'delta_date'=1 and count 'delta_date'>=3 
0

Простое изменение исходного кода должно заставить его работать:

select code, FOOD,grp, count(*) as NumInSequence, min([date]) AS MIN_date, max([date]) AS MAX_Date 
from (select CODE,FOOD,[DATE],(DATEDIFF(D,'1/1/1900',[date])) - row_number() over (partition by code,FOOD order by [date]) as grp from @T t) t 
group by code, FOOD, grp 
HAVING count(*) >= 3 
order by code 

По преобразование внутренней даты в int через дни с некоторой базовой даты «1/1/1900», создается значение int, которое теперь можно использовать в вашем существующем коде! Кроме того, я добавил Food Group в строку row_number(), чтобы найти только совпадения, которые также включают пользователь/элемент Combo.

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