获取所有主题,按其上次发布日期在论坛中排序

时间:2009-10-16 19:15:07

标签: sql sql-server tsql

我正在写一个论坛。我有一个TOPICS表和一个POSTS表。在POSTS表中,我有一个TopicId字段和一个日期字段。

我希望在单个SQL查询中获取按其上次发布日期排序的所有主题。我怎么能这样做?

编辑:帖子的日期位于POST表格中。我想检查每篇文章的最后一篇文章,然后检查它的日期,然后按这个日期排序。

5 个答案:

答案 0 :(得分:1)

这是一个快速而肮脏的例子:

CREATE TABLE dbo.Posts
(
    PostID INT,
    TopicID INT,
    AuthorID INT,
    PostDate SMALLDATETIME
);
GO
INSERT dbo.Posts SELECT 1,1,1,CURRENT_TIMESTAMP-1;
INSERT dbo.Posts SELECT 2,1,1,CURRENT_TIMESTAMP-0.5;
INSERT dbo.Posts SELECT 3,1,1,CURRENT_TIMESTAMP;
INSERT dbo.Posts SELECT 4,1,1,CURRENT_TIMESTAMP-2;
INSERT dbo.Posts SELECT 5,2,1,CURRENT_TIMESTAMP-0.75;
GO
;WITH x AS 
(
    SELECT
      TopicID,
      PostID,
      PostDate, 
      rn = ROW_NUMBER() OVER
      (
        PARTITION BY TopicID
        ORDER BY PostDate DESC
      )
    FROM dbo.Posts
)
SELECT TopicID, PostID, PostDate
    FROM x
    WHERE rn = 1;
GO

至于hainstech建议的索引视图,我想他的意思是这样的:

CREATE VIEW dbo.MaxPostDate
WITH SCHEMABINDING
AS
    SELECT 
        TopicID,
        MaxPostDate = MAX(PostDate)
    FROM
        dbo.Posts
    GROUP BY
        TopicID;
GO
CREATE UNIQUE CLUSTERED INDEX foo ON dbo.MaxDate(TopicID);
GO

当然,这不合法:

.Net SqlClient Data Provider: Msg 10125, Level 16, State 1, Line 1
Cannot create index on view "foo.dbo.MaxDate" because it uses aggregate "MAX".
Consider eliminating the aggregate, not indexing the view, or using alternate
aggregates. For example, for AVG substitute SUM and COUNT_BIG, or for COUNT,
substitute COUNT_BIG.

答案 1 :(得分:0)

Hope this will help you

select ...,MAX(p.Date)
  from topics T 
  inner join posts P
  on T.TopicId = P.TopicId 
  Group by T.topicName
  order by Max(P.date)  

答案 2 :(得分:0)

SELECT t.Name, MAX(p.Date)
FROM Topics t
JOIN Posts p ON p.TopicID = t.ID
GROUP BY t.Name
ORDER BY MAX(p.Date)

答案 3 :(得分:0)

有几种方法可以做你所要求的。我使用派生表来执行此类操作,但如果您使用的是SQL Server 2005,则可以使用公用表表达式执行此操作。

基本上你是在创建一个包含主题ID和MAX(日期)的表,并加入其中。

示例脚本:

If (object_ID('Posts') is not null) drop table Posts
If (object_ID('Topics') is not null) drop table Topics
GO
create table Topics (
TopicID int identity(1,1) primary key, 
TopicName varchar(100))
go

Create Table Posts (
PostID int identity(1,1) primary key,
TopicID int references Topics,
Title varchar(100),
PostDate datetime)
GO

Insert into Topics(TopicName) Values ('Math')
Insert into Topics(TopicName) Values ('English')
Insert into Topics(TopicName) Values ('Other')
Insert into Posts(TopicID, Title, PostDate) values (1, 'On numbers 1', GETDATE()-7)
Insert into Posts(TopicID, Title, PostDate) values (1, 'On numbers 2', GETDATE()-2)
Insert into Posts(TopicID, Title, PostDate) values (2, 'On words 1', GETDATE()-4)
Insert into Posts(TopicID, Title, PostDate) values (2, 'On words 2', GETDATE())
Insert into Posts(TopicID, Title, PostDate) values (3, 'WTF? 1', GETDATE()-3)
Insert into Posts(TopicID, Title, PostDate) values (3, 'WTF? 2', GETDATE()-1)
GO

--Derived table
Select TopicName, LastPostDate  from Topics T
Inner join (Select TopicID, MAX(PostDate) as LastPostDate 
            from Posts P 
            group by TopicID) as LastPostTable
on T.TopicID=LastPostTable.TopicID
order by LastPostDate desc;

--CTE (SQL Server 2005+)
With CTE_LastPostTable (TopicID, LastPostDate)
as 
(Select TopicID, MAX(PostDate) as LastPostDate 
            from Posts P 
            group by TopicID)
Select TopicName, LastPostDate=coalesce(LastPostDate, '1899-01-01')  from Topics T
Left outer join  CTE_LastPostTable CTE
on T.TopicID=CTE.TopicID
order by LastPostDate desc

您可以使用左外部联接切换内部联接,并在日期列周围合并以捕获任何尚未发布帖子的主题。

With CTE_LastPostTable (TopicID, LastPostDate)
as 
(Select TopicID, MAX(PostDate) as LastPostDate 
            from Posts P 
            group by TopicID)
Select TopicName, LastPostDate=coalesce(LastPostDate, '1899-01-01')  from Topics T
Left outer join  CTE_LastPostTable CTE
on T.TopicID=CTE.TopicID 
order by LastPostDate desc

克里斯

答案 4 :(得分:0)

对于大多数类似于论坛的网络应用程序,您将希望使用类似索引视图的内容来维护每个论坛的最新帖子/帖子等。索引视图很适合这一点,因为它们的开发速度非常快。否则,您可以推出自己的解决方案,该解决方案基于触发器(或sprocs / etc)维护类似的非规范化视图/表。我见过的大多数论坛都有10:1或100:1的读写比例,因此从性能角度看,这种非规范化的视图/表通常非常值得。