选择具有最大 ID 和特定条件的行

Posted

技术标签:

【中文标题】选择具有最大 ID 和特定条件的行【英文标题】:Select the row with the biggest ID and a specific condition 【发布时间】:2015-08-12 08:51:16 【问题描述】:

我有一个具有以下结构的表 cmets:

CommentId (int), 
CommentText (nvarchar(max))
EditedBy (nvarchar(max))
ParentCommentId (int)
CaseId (int)

对于特定的caseId,我想选择最新的评论文本以及EditedBy 列。

例如,如果有人添加评论表,则

CommentId   CommentText          EditedBy     ParentCommentId   CaseId
   1         ParentComment1         ABC          NULL               1 
   2         ParentComment2         ABC          NULL               1 

现在,如果有人编辑该评论,表格将如下所示

CommentId   CommentText          EditedBy     ParentCommentId   CaseId
   1         ParentComment1       ABC          NULL               1 
   2         ParentComment2       ABC          NULL               2
   3         Comment2             DEF          1                  1 

此编辑可以进行任意次数 我想选择最新的评论以及历史。 在这种情况下,我的数据集应该是这样的:

CaseId   CommentId   CommentText       Predicate
  1       3           Comment2         Created By ABC , Updated by DEF
  1       2           ParentComment2   Created By ABC

这是问题的简化版本。 TIA

【问题讨论】:

你有什么 sql-server 版本?到目前为止你尝试了什么/ select TOP 1 * from Comment hc INNER JOIN Comment hc1 ON hc.ParentCommentId = hc1.CommentId ORDER BY hc.CommentId DESC 它只给我第一条评论,但没有谓词。当一个案例有多个 cmets 时,这也不起作用。我正在使用 SQL Server 2014 Optimal way to concatenate/aggregate strings 的可能重复项 看看这些问题 - ***.com/questions/13639262/… 和 ***.com/questions/3442931/…。我想他们有你的答案。 【参考方案1】:

您可以使用FOR XML PATH 创建您的谓词列。像这样的。

SQL Fiddle

样本数据

CREATE TABLE Comment
    ([CommentId] int, [CommentText] varchar(8), [EditedBy] varchar(3), [ParentCommentId] varchar(4), [CaseId] int);

INSERT INTO Comment
    ([CommentId], [CommentText], [EditedBy], [ParentCommentId], [CaseId])
VALUES
    (1, 'Comment1', 'ABC', NULL, 1),
    (2, 'Comment2', 'DEF', '1', 1);

查询

;WITH CTE AS 
(
SELECT CommentID, CommentText,EditedBy,ParentCommentID,CaseID,ROW_NUMBER()OVER(PARTITION BY Caseid ORDER BY CommentID DESC) RN
FROM Comment
), CTE2 as
(
SELECT CommentID, CommentText,EditedBy,ParentCommentID,CaseID,
  (
    SELECT
    CASE WHEN ParentCommentID IS NULL THEN 'Created By ' ELSE ', Updated By ' END
    + EditedBy
    FROM CTE C1
    WHERE C1.CaseID = C2.CaseID
    ORDER BY CommentID ASC
    FOR XML PATH('')
  ) as Predicate
FROM CTE C2
WHERE RN = 1
)
SELECT CaseID,CommentID, CommentText,Predicate FROM CTE2;

编辑

如果您不想为每个更新了caseid 的用户重复Updated By,请使用以下CASE

CASE WHEN ParentCommentID IS NULL THEN 'Created By ' + EditedBy + ', Updated By' ELSE '' END,
CASE WHEN ParentCommentID IS NOT NULL THEN ', ' + EditedBy ELSE '' END

代替

    CASE WHEN ParentCommentID IS NULL THEN 'Created By ' ELSE ', Updated By ' END + EditedBy

输出

| CaseID | CommentID | CommentText |                      Predicate |
|--------|-----------|-------------|--------------------------------|
|      1 |         2 |    Comment2 | Created By ABC, Updated By DEF |

编辑 2

使用递归 CTE 来实现您的预​​期输出。像这样的。

SQL Fiddle

查询

;WITH CTEComment AS 
(
SELECT CommentID as RootCommentID,CommentID, CommentText,EditedBy,ParentCommentID,CaseID
FROM Comment
WHERE ParentCommentID IS NULL
UNION ALL 
SELECT CTEComment.RootCommentID as RootCommentID,Comment.CommentID, Comment.CommentText,Comment.EditedBy,Comment.ParentCommentID,Comment.CaseID
FROM CTEComment
INNER JOIN Comment
    ON CTEComment.CommentID = Comment.ParentcommentID
        AND CTEComment.CaseID = Comment.CaseID
), CTE as  
(
SELECT CommentID,RootCommentID,CommentText,EditedBy,ParentCommentID,CaseID,ROW_NUMBER()OVER(PARTITION BY CaseID,RootCommentID ORDER BY CommentID DESC) RN
FROM CTEComment
), CTE2 as
(
SELECT CommentID, CommentText,EditedBy,ParentCommentID,CaseID,
  (
    SELECT
    CASE WHEN ParentCommentID IS NULL THEN 'Created By ' ELSE ', Updated By ' END
    + EditedBy
    FROM CTE C1
    WHERE C1.CaseID = C2.CaseID
    AND C1.RootCommentID = C2.RootCommentID
    ORDER BY CommentID ASC
    FOR XML PATH('')
  ) as Predicate
FROM CTE C2
WHERE RN = 1
)
SELECT CaseID,CommentID, CommentText,Predicate FROM CTE2;

输出

| CaseID | CommentID |    CommentText |                      Predicate |
|--------|-----------|----------------|--------------------------------|
|      1 |         3 |       Comment2 | Created By ABC, Updated By DEF |
|      2 |         2 | ParentComment2 |                 Created By ABC |

【讨论】:

这只是给我最新的,也可能有一个案例有多个 cmet,请参阅编辑 能否更新您的示例数据和预期输出。根据您当前的预期输出,每个案例似乎只有一条评论【参考方案2】:
You can use this method
DECLARE @CaseId [int];
SET @CaseId=1`enter code here`
DECLARE @GeneratedBy [nvarchar](max);
SET @GeneratedBy=(SELECT  EditBy from Comment  WHERE ParentCommentId is NULL AND CaseId = @CaseId)
PRINT @GeneratedBy;
SELECT CaseId , CommentId , CommentText  , 'Created By '+@GeneratedBy+ ', Updated By ' +EditBy  AS Predicate FROM Comment
WHERE CaseId = @CaseId AND ParentCommentId=(SELECT  max(ParentCommentId) from Comment  WHERE  CaseId = @CaseId)

【讨论】:

【参考方案3】:

您可以简单地使用自联接来获得结果:

在下面找到查询:

select a.CaseId,b.CommentId, b.CommentText,'Created By '+a.EditedBy +', update by '+b.EditedBy as Predicate
from Comment a
inner join Comment b
on a.CaseId=b.CaseId
where a.CommentId<b.CommentId

【讨论】:

以上是关于选择具有最大 ID 和特定条件的行的主要内容,如果未能解决你的问题,请参考以下文章

如何选择具有最大值的行的所有列

选择具有最大值的行的 ID

从表中选择具有最大日期的行

SQL选择具有最大和最小日期的行

Oracle SQL 查询为包含相同 ID 的行提取最大日期的数据

如何从Oracle中的另一个子查询中选择具有最大列的行