2016-08-18 3 views
1

У меня есть сценарий, где у меня естьПолучение минимум колонки на основе другого поля

Id|rank| date 
1 | 7 |07/08/2015 
1 | 7 |09/08/2015 
1 | 8 |16/08/2015 
1 | 8 |17/08/2015 
1 | 7 |19/08/2015 
1 | 7 |15/08/2015 
2 | 7 |01/08/2015 
2 | 7 |02/08/2015 
2 | 8 |16/08/2015 
2 | 8 |17/08/2015 
2 | 7 |26/08/2015 
2 | 7 |28/08/2015 

Мое искомое решение является

1 | 7 |07/08/2015 
1 | 8 |16/08/2015 
1 | 7 |15/08/2015 
2 | 7 |01/08/2015 
2 | 8 |16/08/2015 
2 | 7 |26/08/2015 

т.е. для каждого блока Ид и ранга я хочу минимум даты. Я пробовал использовать цикл while, поскольку есть тысячи записей, на которые требуется загрузить 2 часа. Есть ли другой способ сделать, пожалуйста, предложите.

+0

Искать что-то вроде «SQL первой строки в группе» Вот один: http://stackoverflow.com/questions/3800551/select-first-row-in-each-group- по-группе – shawnt00

+1

Почему 1,7,15/08/2015 повторяется дважды один раз за 07/08 и 15/08 – TheGameiswar

+0

Нет, это не повторяется ... 1 и 7 повторяются, так как я хочу, чтобы выход для определенной партии id и rank – user2941762

ответ

0

Здесь запрос с использованием row_number()

;WITH cte_rec 
    as (SELECT Id,Rank,Date 
        ,ROW_NUMBER()OVER (partition by Id,Rank ORDER BY date) as RNO 
     FROM YourTable) 
     SELECT Id,Rank,Date 
     FROM cte_rec 
     WHERE RNO =1 
+0

Спасибо unni, но это не приведет к результату желания – user2941762

1

Для каждой строки дают уникальный номер строки, используя необходимый порядок. (Поскольку я получаю Идентификатор важнее, чем дата и дата, более важны, чем ранг).

Вставьте итоговую таблицу в себя, используя номера строк, сдвинутые на одну строку (d1.RowNum = d2.RowNum+1).

Выберите только строки, которые соединены с строками «другого блока» (d1.Id <> d2.Id or d1.Rank <> d2.rank).

В зависимости от направления перемещения и выбранной таблицы будет выбрана максимальная или минимальная дата.

Не забывайте, что «кромка края» - ряд, который из-за смещения не может быть соединен (вот почему не inner join и d1.RowNum = 1 состояние используется).

;WITH dataWithRowNums as (
    select Id, Rank, Date, 
     RowNum = ROW_NUMBER() OVER (ORDER BY Id,date,rank) 
    from YourTable 
) 
select d1.Id, d1.Rank, d1.Date 
from dataWithRowNums d1 
left join dataWithRowNums d2 
    on d1.RowNum = d2.RowNum+1 and (d1.Id <> d2.Id or d1.Rank <> d2.rank) 
where not d2.Id is null or d1.RowNum = 1 

Этот код возвращает результат немного отличается от вашей:

Id Rank Date 
1 7 2015-08-07 
1 8 2015-08-16 
1 7 2015-08-19 <-- you've got here 2015-08-15 
2 7 2015-08-01 
2 8 2015-08-16 
2 7 2015-08-26 

В блоке (Ранг 8 Id 1) начали на 16/08, так грести 15/08 для ранга 7 связан с первым блоком (rank7 Id1).

Если вы по-прежнему нужна ваша сортировкой (так 15/08 ранг 7 связан со вторым блоком (rank7 id1)), то вы должны предоставить свои собственные данные RowSorting, а затем спросить здесь о другом решении для другой задачи)

0
This is what I have tried and is running as expected 
create table #temp 
    (
      iden int identity(1,1), 
      ID int, 
      [rank] int, 
      [date] date, 
      dr_id int, 
      rownum_id int, 
      grouprecord int 
    ) 


    Insert into #temp(id,rank,date) 
    select 1 , 7 ,'07/08/2015' 
    union all select 1 , 7 ,'09/08/2015' 
    union all select 1 , 8 ,'08/16/2015' 
    union all select 1 , 8 ,'08/17/2015' 
    union all select 1 , 7 ,'08/19/2015' 
    union all select 1 , 7 ,'08/15/2015' 
    union all select 2 , 7 ,'08/01/2015' 
    union all select 2 , 7 ,'08/02/2015' 
    union all select 2 , 8 ,'08/16/2015' 
    union all select 2 , 8 ,'08/17/2015' 
    union all select 2 , 7 ,'08/26/2015' 
    union all select 2 , 7 ,'08/28/2015' 


    update t1 
    set dr_id = t2.rn 
    from #temp t1 inner join 
    (select iden, dense_rank() over(order by id) as rn from #temp) t2 
    on t1.iden = t2.iden 


    update t1 
    set rownum_id = t2.rn 
    from #temp t1 inner join 
    (select iden, row_number() over(partition by dr_id order by id) as rn from #temp) t2 
    on t1.iden = t2.iden 




    select *,row_number() over(order by iden)rn into #temp1 from 
    (    
         select t2.* 
        from #temp t1 inner join #temp t2 
        on (t1.dr_id = t2.dr_id or t2.dr_id = (t1.dr_id +1)) and (t1.rank<>t2.rank or t2.dr_id = (t1.dr_id +1)) 
        and t2.iden = t1.iden + 1 
    )a 





    declare @id int,@miniden int,@maxiden int,@maxid int 
    set @id = 1 
    select @maxid = max(iden) from #temp 

    while exists(select 1 from #temp1 where rn = @id) 
    begin 
      Select @miniden = iden from #temp1 
      where rn = @id 

      Select @maxiden = iden from #temp1 
      where rn = @id+1 

      update #temp 
      set grouprecord = @id +1 
      where iden between @miniden and @maxiden 

    IF(@maxiden IS NULL) 
    BEGIN 
      Update #temp 
      set grouprecord = @id +1 
      where iden between @miniden and @maxid 
    END 

      set @id = @id + 1 
      SET @miniden =NULL 
      SET @maxiden = NULL 
    end 

    UPDATE #TEMP 
    SET GROUPRECORD = 1 
    WHERE GROUPRECORD IS NULL 



    select min(date) as mindate,grouprecord from #temp 
    group by grouprecord 

Спасибо всей помощь :)

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