задача SQL server

Elen13

есть таблица - посещение сотрудниками точек
содежрится ИД сотрудника, ИД точки, месяц, дата визита, дополнительная информация
в течении периода (за месяц) сотрудник одну точку может посетить несколько раз
необходимо выбрать из этой таблицы по данному сотруднику, за указанный месяц все строки, в которых отображена информация по самому последнему за период визиту по всем посещённым точкам
как это сделать?

zorin29


SELECT * FROM Visits v
INNER JOIN (
SELECT PointID, MAX(VisitDate) as Maate FROM Visits
WHERE EmployeeName=@employee AND Month=@month
GROUP BY PointID
) v2 ON v.VisitDate = v2.Maate

mbolik1

Если SQL Server 2008:

SELECT *
FROM (SELECT row_number over (partition by PointID order by VisitDate desc) rn
, V.*
FROM Visits V
WHERE EmployeeName=@employee AND Month=@month
)
WHERE rn = 1

Elen13

спасибо!
имеет ли смысл сделать табличную функцию для выборки максимальных дат?

hprt

если делать, то обязательо inline! (есть два типа - inline и multi-statement а так - как хочешь

Elen13

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

hprt

да

lilia13

SELECT *
FROM (SELECT rank over (partition by PointID order by VisitDate desc) rn
, V.*
FROM Visits V
WHERE EmployeeName=@employee AND Month=@month
)
WHERE rn = 1
Может быть время не указано.

dava

Ранк-то чего, роунамбер же правильнее, а ранг, теоретически, может одинаковый быть для одной точки, хоть на корректных данных это и не реально.
Стандартная задача на top N with ties:
 
select  top 1 with ties
id_employee,
id_point,
month,
visit_date,
additional_info
from table_of_visit a
where a.id_employee = <сотрудник>
month = <месяц>
order by
ROW_NUMBER over (partition by id_point order by visit_date desc)

hprt

Я думаю, top with ties будет менее эффективен фильтрации по row_number из-за сортировки

dava

вроде бы идентичные механизмы с идентичными операциями, или я что-то упускаю?
вообще, больше 3 лет на ms sql уже не писал, могу ошибаться насчёт эффективности, конечно

lilia13

Сотрудник может посетить 2 (или больше) точки за день и если нет времени посещения, то непонятно какую точку брать. row_number уберет все кроме одной, rank оставит все (но если время будет указано, то rank все равно правильно сработает).

hprt

Нет конечно, с with ties у тебя две операции сортировки - для row_number + order by, с фильтрацией - только одна.
К сожалению, не могу скопировать детализацию/планы - сервер в другой сети, но мои слова подтверждаются - у меня фильтрация на 200К строк примерно вдвое быстрее

dava

Сотрудник может посетить 2 (или больше) точки за день и если нет времени посещения, то непонятно какую точку брать. row_number уберет все кроме одной, rank оставит все (но если время будет указано, то rank все равно правильно сработает).
В задаче подразумевается, что нужно выбрать одну точку. Например, тебе нужно будет делать из результатов запроса select into в переменную. В случае двух строк выпадет ошибка.
Хотя там в условии задачи написано, что нужно вытащить одну запись по каждой точке, так что это утверждение, как и твоё, тоже не имеет практического смысла.

dava

Нет конечно, с with ties у тебя две операции сортировки - для row_number + order by, с фильтрацией - только одна.
Странно, ведь в order by при ties не указывается, в каком порядке отображать точки, указывается только partition по ним. Выходит, что второй сортировки всё таки не происходит, так как нет информации, по чему её производить.
Но если ты говоришь, что без ties быстрее, то определённо в моём решении есть какой-то изъян.

hprt

Как работает with ties: захватывает первые top (N) и добавляет строки, имеющие тот же порядок сортировки с последней, не вошедшие в N. Но для этого все равно идет сортировка - собственно, по row_number в нашем случае

Elen13

Сотрудник может посетить 2 (или больше) точки за день и если нет времени посещения, то непонятно какую точку брать. row_number уберет все кроме одной, rank оставит все (но если время будет указано, то rank все равно правильно сработает).
так и есть - в день визитов более одного, в разные точки (в одну и ту же точку двух визитов в день быть не может)
в "дополнительной информации" - содержатся прочие переменные, по которым потом рассчёт будет идти
вот её-то и надо вытащить по всем посещённым торговым точкам, самую актуальную на данный момент

dava

Как работает with ties: захватывает первые top (N) и добавляет строки, имеющие тот же порядок сортировки с последней, не вошедшие в N. Но для этого все равно идет сортировка - собственно, по row_number в нашем случае
Так ведь это одна сортировка, по row_number единожды, а партиции между собой не сортируются.

hprt

для row_number все равно Sort в плане есть
Оставить комментарий
Имя или ник:
Комментарий: