sql server обнаруживает первое и последнее появление и заменяет их

#sql-server #tsql #sql-server-2012

#sql-server #tsql #sql-server-2012

Вопрос:

Я написал запрос для извлечения символов сотрудников для определенного диапазона дат.. что дало такой результат

 Name     Type    Date         Code
----     ----    --------      ---
Mark     Dev    25/02/2014      a
Mark     Dev    26/02/2014      b
Mark     Dev    27/02/2014      c
Mark     Dev    28/02/2014      a
Mark     Dev    29/02/2014      b
Mark     Dev    30/02/2014      c
Rob      Dev    25/02/2014      c
Rob      Dev    26/02/2014      a
Rob      Dev    27/02/2014      b
Rob      Dev    28/02/2014      b
Rob      Dev    29/02/2014      c
Rob      Dev    30/02/2014      a
Pete     Dev    25/02/2014      a
Pete     Dev    26/02/2014      a
Pete     Dev    27/02/2014      a
Pete     Dev    28/02/2014      a
Pete     Dev    29/02/2014      b
Pete     Dev    30/02/2014      c
 

Я хотел бы заменить первое вхождение ‘b’ [code] и последнее вхождение ‘b’ на ‘x’ для каждого сотрудника..

Мой запрос выглядит следующим образом..

 Select  e.Name
       ,e.Type
       ,l.Date
       ,lc.Code
  From
         Employee  e
                      Inner Join leave l on e.empid = l.empid
                      Inner Join leaveCode lc on lc.lcodeid = l.lcodeid
  order by e.identfier,l.date
 

Итак, как я могу выбрать все данные, заменив первое и последнее вхождение ‘b’..

Я пробовал..

 Select 
       data.Name,
       data.Type,
       data.Date,
       (CASE WHEN ((Select TOP 1 data.Date from data where data.code = 'b') = data.Date) THEN 'x'  END) AS Code
From
(Select  e.Name
       ,e.Type
       ,l.Date
       ,lc.Code
  From
         Employee  e
                      Inner Join leave l on e.empid = l.empid
                      Inner Join leaveCode lc on lc.lcodeid = l.lcodeid
  order by e.identfier,l.date) as data
 

Комментарии:

1. Вы хотите заменить их в таблице или в результате запроса?

2. Привет, спасибо за ответ.. Я хочу заменить их в результате запроса.. На самом деле я хочу получить свой результат, поскольку я получил свой предыдущий запрос, но заменил первое и последнее вхождения ‘b’ для каждого сотрудника

Ответ №1:

Я бы добавил a row_number() к каждой строке, разделенной по имени, упорядоченной по дате.

Это дает каждой строке для метки, например, число 1-6.

Затем вы запрашиваете min/max идентификатор по имени where type='x' и присоединяете его к исходным данным.

     declare @data table (Name nvarchar(100), Type nvarchar(10), Date date, Code nvarchar(1))

    insert into @data
    select 'Mark',     'Dev',    '2014-04-25',      'a' union all
    select 'Mark',     'Dev',    '2014-04-26',      'b' union all
    select 'Mark',     'Dev',    '2014-04-27',      'c' union all
    select 'Mark',     'Dev',    '2014-04-28',      'a' union all
    select 'Mark',     'Dev',    '2014-04-29',      'b' union all
    select 'Mark',     'Dev',    '2014-04-30',      'c' union all
    select 'Rob',      'Dev',    '2014-04-25',      'c' union all
    select 'Rob',      'Dev',    '2014-04-26',      'a' union all
    select 'Rob',      'Dev',    '2014-04-27',      'b' union all
    select 'Rob',      'Dev',    '2014-04-28',      'b' union all
    select 'Rob',      'Dev',    '2014-04-29',      'c' union all
    select 'Rob',      'Dev',    '2014-04-30',      'a' union all
    select 'Pete',     'Dev',    '2014-04-25',      'a' union all
    select 'Pete',     'Dev',    '2014-04-26',      'a' union all
    select 'Pete',     'Dev',    '2014-04-27',      'a' union all
    select 'Pete',     'Dev',    '2014-04-28',      'a' union all
    select 'Pete',     'Dev',    '2014-04-29',      'b' union all
    select 'Pete',     'Dev',    '2014-04-30',      'c'

    ;with rowid as (
         select row_number() over(partition by name order by name, date) as id,
         *
         from @data)

    select t1.*
case when t1.id=filter.minid then 'first x' else null end as [firstreplace],
       case when t1.id=filter.maxid then 'last x' else null end as [lastreplace]
    from rowid t1
    join (select min(id) as minid, max(id) as maxid, name from rowid where code='b' group by name) as filter
       on t1.name=filter.name
       and (t1.id=filter.minid or t1.id=filter.maxid)
 

Скрипка здесь.

Если вам нужно минимальное значение, просто уберите максимальное значение из строки and (t1.id=filter.minid *or t1.id=filter.maxid*) и наоборот..

Комментарии:

1. Похоже, что этот запрос не возвращает никаких «x». Я что-то упускаю?

2. Я подумал, что, показывая ему первые / последние события для каждого имени, он может обновить его, но никогда не помешает добавить его.