2009-10-16 2 views
0

나는 포럼을 작성하고 있습니다. 나는 TOPICS 테이블과 POSTS 테이블을 가지고 있습니다. POSTS 테이블에는 TopicId 필드와 날짜 필드가 있습니다.포럼에서 마지막 게시일 순으로 정렬 된 모든 주제 얻기

지난번 게시물 날짜순으로 정렬 된 모든 항목을 단일 SQL 쿼리로 가져오고 싶습니다. 어떻게해야합니까?

편집 : 게시물의 날짜는 POST 테이블에 있습니다. 모든 게시물의 마지막 게시물이 무엇인지 확인한 다음 날짜를 확인한 다음이 날짜까지 스레드를 주문하고 싶습니다.

답변

1

가 여기에 신속하고 더러운 예입니다 : 물론

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 

, 이것은 법적되지 않습니다 : hainstech에 의해 제안 인덱싱 된 뷰에 관해서는

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 

, 나는 그가 이런 일을 의미 상상 :

.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 번 반환합니다. –

+0

방금 ​​편집 한 것을 보았습니다. – anishMarokey

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

매우 빠르게 개발할 수 있습니다. 그렇지 않으면 트리거 (또는 sprocs/etc)를 기반으로 비슷한 비정규 화 된보기/테이블을 유지 관리하는 자체 솔루션을 롤백 할 수 있습니다. 내가 본 대부분의 포럼은 10 : 1 또는 100 : 1의 읽기 쓰기 비율을 가지고 있기 때문에이 비표준보기/표는 일반적으로 성능 측면에서 보람 있습니다.

+0

인덱싱 된 뷰는 COUNT_BIG()와 같은 집계를 유지할 수 있지만 인덱싱 된 뷰를 사용하여 MAX (PostDate)를 추적하도록 제안하려면 어떻게합니까? 생성 테이블 (SMALLDATETIME b를 \t INT, \t) 를 dbo.x; GO CREATE VIEW dbo. \t AS SCHEMABINDING WITH Y 는 \t \t A, \t \t B = MAX (b) \t \t \t FROM dbo.x \t \t \t GROUP 부산물을 선택; GO 고유 한 클러스터 된 인덱스 foo를 만듭니다. dbo.x (a); GO "foo.dbo.MaxDate"뷰에 집계 "MAX"를 사용하므로 인덱스를 만들 수 없습니다. 집계를 제거하거나 뷰를 인덱싱하지 않거나 대체 집계를 사용하는 것을 고려하십시오. 예를 들어 AVG 대체 SUM 및 COUNT_BIG의 경우 또는 COUNT의 경우 COUNT_BIG를 대체하십시오. –

+0

죄송합니다, 서식이 끔찍합니다. 대답에 내 재빠른 보여 드리죠. –

+0

@Aaron 물론 100 % 정확합니다. 인덱스 뷰를 사용한 가장 최근의 사용법은 1 년이 넘었고 이러한 기본 제한 사항을 잊어 버린 것 같습니다. 귀하의 우수한 disproof 주셔서 감사합니다 :) 나는 여전히 어떤 수단 (트리거/sproc/유모 프로세스)에 의해 유지됩니다 비정규화된 가장 최근 게시물을 권장합니다. 이것이 이것이 최선의 방법이라는 것을 증명하는 것은 아니지만 vbulletin 스키마에서 이와 동일한 접근법을 생각해 냈습니다. – ahains

관련 문제