Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Простая задача  [new]
SiebelCRM
Member

Откуда:
Сообщений: 42
Таблица. Три поля: Клиент, Дата заказа, Товар. Нужен запрос, который покажет последний товар для каждого клиента. Как лучше?
16 июн 10, 00:05    [8947467]     Ответить | Цитировать Сообщить модератору
 Re: Простая задача  [new]
iljy
Member

Откуда:
Сообщений: 8711
SiebelCRM,

лучше - указывать версию сервера. В зависимости от версии это может быть либо ROW_NUMBER, либо обычный max + group by + join.
16 июн 10, 00:28    [8947557]     Ответить | Цитировать Сообщить модератору
 Re: Простая задача  [new]
Добрый Э - Эх
Guest
SiebelCRM
Таблица. Три поля: Клиент, Дата заказа, Товар. Нужен запрос, который покажет последний товар для каждого клиента. Как лучше?

Вот тебе основные способы решения поставленной задачи:
0) -- Для версии сервера 2005 и выше
select top 1 with ties *
  from [Таблица]
 order by row_number() 
                over(partition by [Клиент] 
                         order by [Дата] desc)

1) -- Для версии сервера 2005 и выше
select *
  from (
         select t.*, row_number() 
                           over(partition by [Клиент] 
                                    order by [Дата] desc) as rn
           from [Таблица] t
       ) v
 where rn = 1;
 
2) -- Для всех версий сервера
select t1.*
  from [Таблица] t1
  left join [Таблица] t2
    on t1.[Клиент] = t2.[Клиент]
   and t1.[Дата] < t2.[Дата]
 where t2.[Клиент] is null;
 
3) -- Для всех версий сервера    
select t1.*
  from [Таблица] t1,
       (
         select [Клиент], max([Дата]) as [Дата]
           from [Таблица]
          group by [Клиент]
       ) v
 where t1.[Клиент] = v.[Клиент]
   and t1.[Дата] = v.[Дата];
   
4) -- Для всех версий сервера
select t1.*
  from [Таблица] t1
 where not exists(
                   select null
                     from [Таблица] t0
                    where t1.[Клиент] = t0.[Клиент]
                      and t1.[Дата] < t0.[Дата]
                 );


5) -- Для всех версий сервера
select t1.*
  from [Таблица] t1
 where [Дата] = (-- Агрегацию можно заменить на TOP 1 + ORDER BY [Дата] DESC
                 select max([Дата])
                   from [Таблица] t0
                  where t1.[Клиент] = t0.[Клиент]
               )
Что из них лучше - зависит от количества данных и их распределения, а также от схемы индексирования.
Попробуй на своих данных все способы. Выбери тот, что покажется тебе наиболее приемлемым.
16 июн 10, 05:29    [8947782]     Ответить | Цитировать Сообщить модератору
 Re: Простая задача  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
6) -- Для версии сервера 2005 и выше
select t1.*
  from [Таблица] t1 cross apply
       (
         select t2.[Клиент], max(t2.[Дата]) as [Дата]
         from [Таблица] t2
         where t2.[Клиент]=t1.[Клиент]
         group by t2.[Клиент]
        ) v
  where t2.[Дата]=t1.[Дата];
16 июн 10, 09:36    [8948033]     Ответить | Цитировать Сообщить модератору
 Re: Простая задача  [new]
Knyazev Alexey
Member

Откуда: Екб -> Мск
Сообщений: 10234
Блог
7) -- Для версии сервера 2005 и выше = 1ому варианту по сути, но через СТЕ

;with cte
as
 (
         select t.*, row_number() 
                           over(partition by [Клиент] 
                                    order by [Дата] desc) as rn
           from [Таблица] t
) 
select * from cte where rn = 1;
16 июн 10, 09:43    [8948067]     Ответить | Цитировать Сообщить модератору
 Re: Простая задача  [new]
iap
Member

Откуда: Москва
Сообщений: 46975
Опечатка
iap
6) -- Для версии сервера 2005 и выше
select t1.*
  from [Таблица] t1 cross apply
       (
         select t2.[Клиент], max(t2.[Дата]) as [Дата]
         from [Таблица] t2
         where t2.[Клиент]=t1.[Клиент]
         group by t2.[Клиент]
        ) v
  where t2.[Дата]=v.[Дата];
16 июн 10, 09:53    [8948126]     Ответить | Цитировать Сообщить модератору
 Re: Простая задача  [new]
SiebelCRM
Member

Откуда:
Сообщений: 42
ОГО! Спасибо, буду пробовать!
16 июн 10, 19:04    [8953168]     Ответить | Цитировать Сообщить модератору
Между сообщениями интервал более 1 года.
 Re: Простая задача  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4602
8) -- Для версии сервера 2012 и выше
select t1.*
  from [Таблица] t1 left join 
       (
         select distinct t2.[Клиент], FIRST_VALUE(t2.[Дата] OVER ORDER BY [Дата] DESC) as [Дата]
         from [Таблица] t2
         where t2.[Клиент]=t1.[Клиент]
         group by t2.[Клиент]
        ) v
  where t2.[Дата]=t1.[Дата];


Сообщение было отредактировано: 25 июн 14, 16:43
25 июн 14, 14:23    [16217512]     Ответить | Цитировать Сообщить модератору
 Re: Простая задача  [new]
Добрый Э - Эх
Guest
???
a_voronin
8) -- Для версии сервера 2012 и выше
select t1.*
  from [Таблица] t1 left join 
       (
         select distinct t2.[Клиент], FIRST_VALUE(t2.[Дата] OVER ORDER BY [Дата] DESC) as [Дата]
         from [Таблица] t2
         where t2.[Клиент]=t1.[Клиент]
         group by t2.[Клиент]
        ) v
  where t2.[Дата]=t1.[Дата];
26 июн 14, 05:20    [16220835]     Ответить | Цитировать Сообщить модератору
 Re: Простая задача  [new]
a_voronin
Member

Откуда: Москва
Сообщений: 4602
Добрый Э - Эх,
Да его надо выкинуть.

a_voronin
8) -- Для версии сервера 2012 и выше
select t1.*
from [Таблица] t1 left join
(
select distinct t2.[Клиент], FIRST_VALUE(t2.[Дата] OVER ORDER BY [Дата] DESC) as [Дата]
from [Таблица] t2
where t2.[Клиент]=t1.[Клиент]
) v
where t2.[Дата]=t1.[Дата];
26 июн 14, 12:00    [16222263]     Ответить | Цитировать Сообщить модератору
 Re: Простая задача  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
Некроманим в стиле КО, при этом лень даже засунуть в тэг SRC и написать без ошибок.

Неужто надо хоть как-то самоутвердится?

Добрый Э - Эх, там минимум 3 ошибки.

А главное, нормально сделать полнофункциональную группировку данных MS не желает.
29 июн 14, 21:19    [16235986]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить