Отображать строки при прокрутке как твиттер, используя хранимую процедуру - PullRequest
0 голосов
/ 18 февраля 2012

У меня есть сайт, который отображает сообщения.Я хочу, чтобы прокрутка сайта велась как твиттер - прокрутка вниз будет отображать все больше и больше постов, бесконечно.Предположим, у меня есть следующие таблицы:

Таблица сообщений для всех сообщений.Каждый пост связан с одним человеком

CREATE TABLE [dbo].[Post](
    [Id] [bigint] IDENTITY(1,1) NOT NULL,
    [PersonId] [int] NOT NULL,
        [PublishDate] [datetime] NOT NULL,
 CONSTRAINT [PK_Post] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,
       ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Таблица PostTag для хранения всех связанных тегов каждого поста.

CREATE TABLE [dbo].[PostTag](
    [PostId] [bigint] NOT NULL,
    [TagId] [int] NOT NULL,
 CONSTRAINT [PK_PostTag] PRIMARY KEY CLUSTERED 
(
    [PostId] ASC,
    [TagId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,
       ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

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

CREATE TABLE [dbo].[UserPersonStatistics](
    [UserId] [bigint] NOT NULL,
    [PersonId] [int] NOT NULL,
    [Counter] [bigint] NOT NULL,
 CONSTRAINT [PK_UserPersonStatistics] PRIMARY KEY CLUSTERED 
(
    [UserId] ASC,
    [PersonId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,
       ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

Для каждого пользователя сайта таблица UserPostStatistics содержит количество проявлений интереса к сообщению.

CREATE TABLE [dbo].[UserPostStatistics](
    [UserId] [bigint] NOT NULL,
    [PostId] [bigint] NOT NULL,
    [Counter] [bigint] NOT NULL,
 CONSTRAINT [PK_UserPostStatistics] PRIMARY KEY CLUSTERED 
(
    [UserId] ASC,
    [PostId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF,
       ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

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

CREATE TABLE [dbo].[UserTagStatistics](
    [UserId] [bigint] NOT NULL,
    [TagId] [int] NOT NULL,
    [Counter] [bigint] NOT NULL,
 CONSTRAINT [PK_UserTagStatistics] PRIMARY KEY CLUSTERED 
(
    [UserId] ASC,
    [TagId] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, 
       ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

Мне нужна хранимая процедура, которая для каждого пользователя возвращает 35 различныхкаждый раз, когда «запоминает» последние 35 сообщений, поэтому они не возвращают те же самые сообщения, и 35 сообщений должны состоять из: 15 сообщений для самого популярного тега (UserTagStatistics) 15 сообщений для самого популярного человека (UserPersonStatistics)) 5 самых популярных сообщений (UserPostStatistics)

Одна проблема заключается в том, что процедура должна возвращать 35 различных сообщений каждый раз.Еще одна проблема заключается в том, что пост может возвращаться один раз как самый популярный пост, один раз как пост самого популярного тега и один раз как пост самого популярного человека.Этот пост следует считать один, а не три раза.Выполнение хранимой процедуры имеет решающее значение.

Я знаю, это очень сложный вопрос.Любые мысли приветствуются.

Круви

1 Ответ

1 голос
/ 18 февраля 2012

Добавьте поле даты и времени «LastViewed» во все таблицы, а затем используйте процедуру, подобную этой. Для повышения производительности просто убедитесь, что для каждой из трех таблиц есть индекс UserID + LastViewed + Counter и UserID + PersonID, и он должен кричать. На самом деле, поскольку UserID + LastViewed + Counter - это практически вся таблица, если это возможно, я бы порекомендовал сделать это кластеризованный индекс для каждой из ваших таблиц, чтобы избежать создания второго индекса, который в основном будет тот же размер, что и необработанный стол.

   create proc GetInfo(@UserId bigint) as
    begin
        update userpersonstatistics 
        set 
            lastviewed=getdate() 
        where 
            userid=@UserID and personid in 
                (
                select top 15 personid from userpersonstatistics
                where 
                    userid=@UserID and 
                    (
                    lastviewed is null or lastviewed != 
                        (select max(lastviewed) from userpersonstatistics
                         where userid=@UserID)
                    )    
                order by counter desc
                )


        select * from UserPersonStatistics 
               where UserID=@UserID and LastViewed  = 
            (select max(lastviewed) from UserTagStatistics)

        --**Repeat the above code for UserPostStatistics and UserTagStatistics
    end

ПЕРЕСМОТРЕННЫЙ ПРОЦЕСС, ОСНОВАННЫЙ НА ВХОДЕ:

 create proc GetInfo(@UserId bigint) as
    begin
        declare @lastviewed datetime
        declare @results TABLE
        (
          StatType varchar(10),
          Counter int,
          PostID
        )

        set @lastviewed = getdate()

        --Person
        insert into @results(StatType,Counter,PostID)
        select 
            'Person',counter,PostID
        from
            UserPersonStatistics
        where 
            userid=@UserID and personid in 
                (
                select top 35 personid from userpersonstatistics
                where 
                    userid=@UserID and 
                    (
                    lastviewed is null or lastviewed != 
                        (select max(lastviewed) from userpersonstatistics
                         where userid=@UserID)
                    )    
                order by counter desc
                )


        --Post
        insert into @results(StatType,Counter,PostID)
        select 
            'Post',counter,PostID
        from
            UserPostStatistics
        where 
            userid=@UserID and Postid in 
                (
                select top 35 Postid from userPoststatistics
                where 
                    userid=@UserID and 
                    (
                    lastviewed is null or lastviewed != 
                        (select max(lastviewed) from userPoststatistics
                         where userid=@UserID)
                    )    
                order by counter desc
                )


        --Tag
        insert into @results(StatType,Counter,TagID)
        select 
            'Tag',counter,TagID
        from
            UserTagStatistics
        where 
            userid=@UserID and Tagid in 
                (
                select top 35 Tagid from userTagstatistics
                where 
                    userid=@UserID and 
                    (
                    lastviewed is null or lastviewed != 
                        (select max(lastviewed) from userTagstatistics
                         where userid=@UserID)
                    )    
                order by counter desc
                )


        --At this point you could have 105 rows of the various types (35*3).
        --You can use whatever algorithm you need to decide the top 35.
        --That may include some weighting.  
            --You may want to consider using the Rank() function.
    end

Если ваш алгоритм должен учитывать верхний счетчик # 1 из каждой категории до # 2, взгляните на функцию Rank () .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...