2009-10-16 71 views
0

我在寫論壇。我有一個TOPICS表和POSTS表。在POSTS表中,我有一個TopicId字段和一個日期字段。獲取所有帖子,通過論壇上的最後發文日期排列

我想在單個SQL查詢中獲取按最後發佈日期排序的所有主題。我怎樣才能做到這一點?

編輯:該帖子的日期是在POST表。我想檢查每篇文章的最後一篇文章,然後檢查它的日期,然後在此日期前排序。

回答

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. 
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) 
+0

x =線程的發帖數量。它會將每個線程返回x次。 – 2009-10-16 19:29:52

+0

剛纔我只看到了你的編輯.. – anishMarokey 2009-10-16 19:39:19

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) 
0

有幾個方法可以做到你的要求。我使用派生表來做這樣的事情,但是如果你使用的是SQL Server 2005,你可以用Common Table Expression來做到這一點。

本質上,你正在創建一個包含主題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 

克里斯

0

對於大多數Web應用程序類似的論壇,你會想使用類似索引視圖的東西,以保持每論壇等最新帖子/線程索引視圖是不錯的,因爲他們是開發速度非常快。否則,您可以推出自己的解決方案,該解決方案基於觸發器(或sprocs/etc)維護類似的非規範化視圖/表格。我見過的大多數論壇的讀寫比都是10:1或100:1,所以從性能的角度來看,這個非規範化的視圖/表格通常是非常值得的。

+0

索引視圖可以維護像COUNT_BIG()這樣的聚合,但你如何建議使用索引視圖來跟蹤MAX(PostDate)? CREATE TABLE dbo.x ( \t一個INT, \t b SMALLDATETIME ); GO CREATE VIEW dbo。ÿ WITH SCHEMABINDING AS \t SELECT \t \t一個, \t \t B = MAX(B) \t FROM \t \t dbo.x \t GROUP BY \t \t一個; GO CREATE UNIQUE CLUSTERED INDEX foo ON dbo.x(a); GO 無法在視圖「foo.dbo.MaxDate」上創建索引,因爲它使用聚合「MAX」。考慮消除聚合,不索引視圖或使用替代聚合。例如,對於AVG替代SUM和COUNT_BIG,或對於COUNT,請替換COUNT_BIG。 – 2009-10-17 01:59:31

+0

對不起,格式是可怕的。我會在回答中顯示我的repro。 – 2009-10-17 02:00:01

+0

@Aaron,當然你是100%正確的。我最近一次使用索引視圖是在一年前,我似乎忘記了這些基本限制。感謝您的出色的disability :) 我仍然建議使用任何方法(觸發器/ sproc/nanny進程)維護的非規範化最近期文章。這並不是說這是最佳做法,但我記得在vbulletin模式中看到了同樣的方法。 – ahains 2009-10-20 20:43:33

相關問題