Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > MS SQL Server > Создание ограниченного списка на MS SQL 2000


Автор: Itsys 6.10.2008, 21:42
Добрый день,

Незнаю,  как это точно называется но задача такая:
В таблице есть три поля: UserId, GoodId, TimeSt

Условия: пользователь (UserId) ходит по интернет-магазину, просматривает товары (GoodId), фиксируется время просмотра (TimeSt).

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

У меня получилось вот что:
Код

CREATE TRIGGER UpdVisits ON [dbo].[Table1] 
FOR INSERT
AS
DECLARE @UserId AS int
DECLARE @GoodId AS int
DECLARE @TimeSt AS datetime
SELECT @UserId = i.UserId, @GoodId = i.GoodId, @TimeSt = i.TimeSt FROM inserted AS i

SELECT * FROM Table1 WHERE UserId = @Userid AND GoodId = @GoodId AND TimeSt != @TimeSt
IF @@ROWCOUNT > 0
    DELETE FROM Table1 WHERE UserId = @Userid AND GoodId = @GoodId AND TimeSt != @TimeSt
ELSE
BEGIN
    SELECT * FROM Table1 WHERE UserId = @Userid
    IF @@ROWCOUNT > 5
    BEGIN
        DECLARE @MinTimeSt as datetime
        SELECT TOP 5 @MinTimeSt = MIN(TimeSt) FROM Table1 WHERE UserId = @Userid GROUP BY TimeSt ORDER BY TimeSt DESC
        DELETE FROM Table1 WHERE TimeSt < @MinTimeSt
    END
END


Может есть более изящное решение данной проблемы?

ЗЫ Заранее спасибо.

Автор: Akina 6.10.2008, 22:42
Конечно. Прочитать справку по синтаксису SELECT ещё раз, обращая особое внимание на TOP n [PERCENT]

Автор: Itsys 7.10.2008, 12:17
Ну и что?

Я, конечно, наверное, тупой но намека не понял....

Автор: Akina 7.10.2008, 12:36
А я задачи не понял. Диковато как-то. Зачем надо удалять данные о посещениях? что, настолько места нехватает? да еще в момент именно посещения - это же тормоза, лишние вычисления.
Храните все посещения, а когда нужно - выбирайте последние 10 просмотренных с последними для каждого из них штампами времени.

Нет, если и вправду с местом проблемы - чистите таблицу при ежедневном (или, если хотите, ежечасном) обслуживании, оставляя для каждой пары юзер-товар только последний просмотр. А если очень надо - то оставляйте только 10 последних.

Автор: Magnifico 7.10.2008, 15:41
может пометку удаления ставить на те которые не  "тор 10"   а потом их удалять- вечерком

Автор: Itsys 7.10.2008, 15:42
А что делать с повторными заходами?

Зашел на один товар, потом на другой, потом на педыдущий в результате в списке действий будет:
Четвертый товар
Второй товар
Третий товар
Второй товар
Первый товар

Тоже не есть хорошо, т.к. в списке товары должны быть уникальными, а при выборке для отображения последних просмотренных (список будет на каждой странице) делать группировку, выбирать из них максимальные по времени и т.д. тоже не супер....

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

Автор: vladimir74 7.10.2008, 15:52
Цитата(Itsys @  7.10.2008,  13:42 Найти цитируемый пост)
Четвертый товар
Второй товар
Третий товар
Второй товар
Первый товар

для этого есть DISTINCT тогда товар два раза не будет повторяться... конечно если прислушаешься совета Akina ....

Автор: Itsys 7.10.2008, 15:58
DISTINCT выбирает неповторяющиеся записи, а в этой таблице повторяющихся записей нет, т.к. у каждой записи есть TimeSt - время входа, а если не учитывать эту колонку, то как отсортировать записи по убыванию времени захода?

Автор: Akina 7.10.2008, 16:14
Код

Select GoodName, Max(TimeStamp)
From Examinations
Group By GoodName

Автор: Magnifico 7.10.2008, 16:23
Цитата

Тоже не есть хорошо, т.к. в списке товары должны быть уникальными


UserId  и GoodId  сделать одной  уникальной связкой

Автор: Itsys 7.10.2008, 16:24
хе.... запрос будет немного другой....
Код

Select GoodName, Max(TimeStamp)
From Examinations WHERE UserName = "SomeUser"
Group By GoodName ORDER BY Max(TimeStamp) DESC


Добавлено через 3 минуты и 9 секунд
Цитата(Magnifico @  7.10.2008,  16:23 Найти цитируемый пост)
UserId  и GoodId  сделать одной  уникальной связкой

Ты имеешь в виду контроль значений, тогда попытка ввода новой записи будет споровождаться ошибкой и, даже если я их буду игнорировать, то я получу на выходе:
Код

Четвертый товар
Третий товар
Второй товар
Первый товар

а не 
Код

Четвертый товар
Второй товар
Третий товар
Первый товар

Автор: vladimir74 7.10.2008, 16:28
ну так сортировать по полю ты можешь. не обязательно его выводить.. иои тебе надо вывести время?

Добавлено через 7 минут и 11 секунд
хммм
Код

[quote=Itsys, 7.10.2008,  14:24, post1661399]Select GoodName, Max(TimeStamp)
From Examinations WHERE UserName = "SomeUser"
Group By GoodName ORDER BY Max(TimeStamp) DESC[/quote]

кажется сам и ответил  smile 

Автор: Itsys 7.10.2008, 16:41
Цитата(vladimir74 @  7.10.2008,  16:28 Найти цитируемый пост)
кажется сам и ответил

Вопрос, что будет лучше и быстрее....  работа тригерра при заходе в карточку товара 5-6% от всех хитов, или выполнение такого запроса при просмотре любой страницы 100% хитов?

Автор: vladimir74 7.10.2008, 17:15
Цитата(Itsys @  7.10.2008,  14:41 Найти цитируемый пост)
Вопрос, что будет лучше и быстрее....  работа тригерра при заходе в карточку товара 5-6% от всех хитов, или выполнение такого запроса при просмотре любой страницы 100% хитов? 

а нельзя повесить этот запрос так чтоб он вызывался только во время захода на карточку товара? все таки мне кажется что запрос будет менее нагрудать сервер. Хотя конечно делать этот запрос при каждом движении юзвера тоже не есть хорошо....

Автор: Itsys 7.10.2008, 17:19
В том то и смысл, чтобы показывать пользователю 10 последних просмотренных товаров, чтобы он мог в любой момент вернуться к ним, а не только когда просматривает другой товар...

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)