2013-10-26 37 views
-1

我有一個表TableA,數據就會像下面:如何獲得最近插入的每個值的記錄有效

PostID PostComments PostTransDate     UserID 
----------------------------------------------------------------- 
10000 VRDFHFGFTR  2013-10-26 21:08:19.817   43434 
10000 GFDGDFSDFF  2013-10-26 21:12:32.323   67576 
10000 HGFHGFBNBF  2013-10-26 21:43:43.545   3232 
10000 JNFNGHFGHG  2013-10-26 21:45:46.656   768 
10000 MJHJNGJHGH  2013-10-26 21:56:32.767   9897 
10001 XCVGFDGDFG  2013-10-26 22:54:54.868   3424 
10001 YTUGFGHHGF  2013-10-26 13:32:54.132   12313 
10001 HGFHFGHGHF  2013-10-26 18:08:32.878   6565 

在這裏,我想獲得的最大價值PostTransDate每個PostIDUserID,PostComments

需要

輸出:

-------------------------------------------------- 
PostID PostComments PostTransDate     UserID 
----------------------------------------------------------------- 
10000 MJHJNGJHGH  2013-10-26 21:56:32.767   9897 
10001 XCVGFDGDFG  2013-10-26 22:54:54.868   3424 

我已經獲得此查詢。

查詢1:

SELECT TT.PostID,TT.PostComments,TT.UserID, TT.PostTransDate 
FROM tableA TT WITH(NOLOCK) 
INNER JOIN 
(
    SELECT PostID,MAX(PostTransDate) PostTransDate 
    FROM tableA T WITH(NOLOCK) 
    GROUP BY PostID 
) T ON T.PostID = TT.PostID AND T.PostTransDate = TT.PostTransDate 

查詢2:

SELECT * 
FROM 
(
SELECT PostID,UserID,PostTransDate,T.PostComments, 
     ROW_NUMBER() OVER(PARTITION BY PostID ORDER BY PostTransDate DESC) RNO 
FROM tableA T 

) N WHERE RNO = 1 

我不能運行這些查詢生產,因爲這些都是非常沉重的。如果任何人有比這更簡化的查詢,請發佈。

+1

表上有什麼索引?有聚集索引嗎?主鍵?到目前爲止,查詢2相對於此頁面上的所有內容都應該是非常高效的,但它取決於可用的索引。很可能這很慢,不是因爲您使用的查詢,而是因爲它正在執行表掃描,因爲沒有可用的索引是有效的。 –

+0

另外,你想怎麼處理關係?兩個人可以同時發表評論到同一篇文章。 –

+0

此表中沒有任何主鍵。我們在PostID列上只有非唯一的集羣索引。以及UserID n其他列上的非唯一非集羣索引。 和incies of Ties.its好的,如果我得到任何record.Per PostID,我應該只有一個UserID,PostComments。 由於此表包含3.2億條記錄。我的團隊告訴我要進一步優化它。 –

回答

1

嘗試了這一點:

SELECT ta1.* FROM tableA ta1 
LEFT JOIN tableA ta2 
ON ta1.postId = ta2.postId AND ta1.postTransDate < ta2.postTransDate 
WHERE ta2.postTransDate IS NULL 

輸出:

| POSTID | POSTCOMMENTS |     POSTTRANSDATE | USERID | 
|--------|--------------|--------------------------------|--------| 
| 10000 | MJHJNGJHGH | October, 26 2013 21:56:32+0000 | 9897 | 
| 10001 | XCVGFDGDFG | October, 26 2013 22:54:54+0000 | 3424 | 

小提琴here

+0

我無法想象爲什麼這會比上面的查詢2更快,尤其是對於大型數據集,我認爲它會慢得多,因爲自連接的讀取成本呈指數級增長。問題是由於缺乏適當的索引,而不是實際使用的語法。 –

+0

我認爲你讓別人困惑我。我在說OP的問題是性能問題,而這種左連接方式實際上很可能會使性能變差。我沒有回答這個問題...... –

+0

大聲笑,是的......我誤讀了你的名字。我相信它應該更多,但值得嘗試一下:)作爲一個附註......我不認爲除了這些選項以外,還有其他方式來查詢這些數據。所以剩下的唯一改進就是在較低的層次上(例如:索引) –

4

有沒有關於你的標的指數結構的想法,無論是否你甚至可以改變它,我會建議這個指數:

CREATE INDEX x ON dbo.TableA(PostID, PostTransDate DESC) 
    INCLUDE (UserID, PostComments); 

這仍然需要掃描才能解決現有的查詢,但它至少會掃描此索引,這比掃描整個表格更有效(假設表中有其他列未被此引用查詢)。

;WITH x AS 
(
    SELECT PostID, UserID, PostTransDate, PostComments, 
    rn = ROW_NUMBER() OVER (PARTITION BY PostID ORDER BY PostTransDate DESC) 
    FROM dbo.TableA 
) 
SELECT PostID, UserID, PostTransDate, PostComments 
    FROM x WHERE rn = 1; 

如果要包括的關係(在同一時間對同一崗位不同用戶的多個評論),只是改變ROW_NUMBER()DENSE_RANK()(當然,實際上,如果你的最後日期後的聚會成員,你可以像使用RANK()一樣有效 - 我不確定它們是否執行任何不同的操作,但它會爲你節省6個字符)。如果你不想包含關係,你可以通過在OVER()之內在訂單中增加一個額外的列來預測它們,例如,如果你想要擁有最長任職期限的用戶,可以在降職後按UserID排序日期。

另一個想法是,如果你不能改變索引或者這不能提供足夠的提升,那就是在另一個表中實現結果。您可以通過觸發器輕鬆應對,但這會影響您的DML工作負載,因此您肯定不應該這樣做來修復這一個查詢。它實際上可能會使應用程序的性能變差。當然,除非您在此表中實現此查詢的所有數據(並且這會非常冗餘),否則它可能無法很好地工作,因爲爲了從主表中檢索數據,您仍然必須加入它,你仍然可能需要在更大的桌子上掃描才能這樣做。如果主表有一個IDENTITY列或其他主鍵,這可能會使事情變得更簡單和更高效,但在完全瞭解底層結構之前,我不打算編寫解決方案。

+0

此表已包含索引。無法創建另一個只爲這個查詢和情況下,我可以顯示任何記錄。 –

相關問題