-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

在这里,我想获得UserID,PostComments每个PostID最大值PostTransDate

需要输出:

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

我已经有得到这个的查询。

查询一:

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

我无法在生产环境中运行这些查询,因为这些查询非常繁重。如果有人有比这更简化的查询,请发布。

4

2 回答 2

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()同样有效地使用 - I'我不确定它们的表现有什么不同,但它会为你节省 6 个字符)。如果您不想包含平局,您可以通过在 order by 内部添加一个额外的列来破坏它们OVER()- 例如,如果您想要拥有最长任期的用户,您可以UserID在降序的发布日期之后排序。

另一个想法,如果你不能改变索引或者这不能提供足够的提升,就是在另一个表中实现结果。您可以使用触发器轻松处理此问题,但它会影响您的 DML 工作负载,因此您当然不应该只修复这个查询。它实际上可能会使您的应用程序的性能变差。当然,除非您在此表中具体化此查询的所有数据(这将是非常多余的),否则它可能无法正常工作,因为为了从主表中检索数据,您仍然必须加入到它,您仍然可能需要对更大的表进行扫描才能这样做。如果主表有一个 IDENTITY 列或其他一些主键,那可能会使事情变得更容易和更高效,但我

于 2013-10-26T16:43:28.450 回答
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 |

在这里摆弄

于 2013-10-26T16:19:13.320 回答