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

Откуда:
Сообщений: 10
Есть таблица

UserID Int UserName varchar RegistrationTime datetime


Необходимо, чтобы функция возвращала минимальное время регистрации, максимальное и разницу между ними.

В функции я использую вью, чтобы сгруппировать данные

SELECT dbo.Users.UserName, dbo.Logs.UserID, MIN(dbo.Logs.RegistrationTime) AS MinTime, MAX(dbo.Logs.RegistrationTime) AS MaxTime, DATEADD(dd, 0, DATEDIFF(dd, 0,
dbo.Logs.RegistrationTime)) AS Date
FROM dbo.Logs INNER JOIN
dbo.Users ON dbo.Logs.UserID = dbo.Users.UserID
GROUP BY dbo.Logs.UserID, dbo.Users.UserName, DATEADD(dd, 0, DATEDIFF(dd, 0, dbo.Logs.RegistrationTime))



А потом накладываю фильтр и обрабатываю данные

SELECT CONVERT(char(10), Date, 105) AS DateString, UserName, UserID,
CONVERT(varchar(5), MaxTime - MinTime, 108) as TimeInterval,
CONVERT(decimal(5, 2),CONVERT(decimal, DATEDIFF(second, MinTime, MaxTime)) / 3600) AS Hours,
CONVERT(varchar(8), MinTime, 108) as MinTime, CONVERT(varchar(8), MaxTime, 108) as MaxTime
FROM LogByTime
WHERE Date between @ReportDateFrom and @ReportDateTo
AND UserID = @UserID
ORDER BY UserName



Я думаю, такой способ явно не оптимальный. Хотелось бы или одним запросом сделать, но тогда возникают проблемы с группировкой и придется несколько раз рассчитывать min, max.

Можно было бы вложенный запрос использовать, конечно. Но не знаю, будет ли он эффективнее в этом случае...
22 июн 09, 12:08    [7327360]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация функции  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
что такое LogByTime ?
22 июн 09, 12:12    [7327400]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация функции  [new]
Алексей2003
Member

Откуда: Москва
Сообщений: 5645
1. DATEADD(dd, 0, DATEDIFF(dd, 0, dbo.Logs.RegistrationTime))
не правильное использование параметров, хотя в данном случае оно ничего не меняет.
2. хранить дату обращения в отдельной колонке (обрабатывать например триггером).
3. если @UserID позволяет отобрать значительные данные, то лучше написать с кучей вычислений max и min, но я почему то думаю, что для аггрегатных функций не будет выполняться по несколько раз пересчет.

для спящего время бодрствования равносильно сну
22 июн 09, 12:18    [7327441]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация функции  [new]
NTNT
Member

Откуда:
Сообщений: 10
1. LogByTime - это вышеупомянутая вьюшка
2. DATEADD(dd, 0, DATEDIFF(dd, 0, dbo.Logs.RegistrationTime)) в принципе работает... А какой способ для вычленения даты более правильный?


3. А как вам такой вариант в смысле быстродействия в сравнении с вью? Я думаю, если добавить еще в таблицу Date и проиндексировать по нему, то будет совсем хорошо?

SELECT CONVERT(char(10), a.Date, 105) AS DateString, a.UserName, a.UserID,
CONVERT(varchar(5), a.MaxTime - a.MinTime, 108) as TimeInterval,
CONVERT(decimal(5, 2),CONVERT(decimal, DATEDIFF(second, a.MinTime, a.MaxTime)) / 3600) AS Hours,
CONVERT(varchar(8), a.MinTime, 108) as MinTime, CONVERT(varchar(8), a.MaxTime, 108) as MaxTime
FROM

(SELECT dbo.Users.UserName, dbo.Logs.UserID, MIN(dbo.Logs.RegistrationTime) AS MinTime,MAX(dbo.Logs.RegistrationTime) AS MaxTime,
DATEADD(dd, 0, DATEDIFF(dd, 0,dbo.Logs.RegistrationTime)) as Date
FROM dbo.Logs INNER JOIN
dbo.Users ON dbo.Logs.UserID = dbo.Users.UserID
WHERE DATEADD(dd, 0, DATEDIFF(dd, 0,dbo.Logs.RegistrationTime)) between @ReportDateFrom and @ReportDateTo
AND dbo.Logs.UserID = @UserID
GROUP BY dbo.Logs.UserID, dbo.Users.UserName, DATEADD(dd, 0, DATEDIFF(dd, 0, dbo.Logs.RegistrationTime))
) a
ORDER by a.UserName
22 июн 09, 13:11    [7327836]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация функции  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
NTNT
3. А как вам такой вариант в смысле быстродействия в сравнении с вью?
Это надо, наверное, Вам на разницу в планах глянуть
22 июн 09, 13:17    [7327879]     Ответить | Цитировать Сообщить модератору
 Re: Оптимизация функции  [new]
Алексей2003
Member

Откуда: Москва
Сообщений: 5645
почитайте про параметры dateadd. 3ий параметр указывается дата, к которой прибавляется параметр 2. а datediff дает разницу между датами типа int, и в силу того, что сервер делает неявное преобразование INT значения к требуемой вам дате, вам сильно повезло. попробуйте вместо dd поставить yy. ваш год улетит далеко за 3000ый.
правильно:
DATEADD(dd, DATEDIFF(dd, 0, dbo.Logs.RegistrationTime), 0) 

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

для спящего время бодрствования равносильно сну
22 июн 09, 13:19    [7327903]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить