SQL:如何检查组内的值?

SQL:如何检查组内的值?,sql,sql-server,group-by,Sql,Sql Server,Group By,我有一张这样的桌子: 对于每个TaskConfigId,都有一个TaskGuid。如果同一TaskConfigId的TaskGuid相同,则它们似乎用于同一任务。通常,TaskStatusId为10或20。当发生某些事情时,TaskStatusId将是其他值,即15。但对于每个任务,它总是有10和20个 因此,如果任务的状态为10和20,则表示没有发生任何特殊情况 现在,我想了解TaskConfigId(例如100)的最后一个CreatedDate是什么时候,它只有TaskStatusId 1

我有一张这样的桌子:

对于每个TaskConfigId,都有一个TaskGuid。如果同一TaskConfigId的TaskGuid相同,则它们似乎用于同一任务。通常,TaskStatusId为10或20。当发生某些事情时,TaskStatusId将是其他值,即15。但对于每个任务,它总是有10和20个

因此,如果任务的状态为10和20,则表示没有发生任何特殊情况

现在,我想了解TaskConfigId(例如100)的最后一个CreatedDate是什么时候,它只有TaskStatusId 10和20,没有其他值。因此,如果TaskConfigId为40,则突出显示的大小写不正确

这是我的

SELECT TOP (1) CreatedDate
FROM [aptfeed].[TaskTracking]
WHERE TaskGuid IN (
        SELECT TaskGuid
        FROM [aptfeed].[TaskTracking]
        WHERE TaskConfigId = 100
        GROUP BY TaskGuid HAVING COUNT(*) = 2               
        )
    AND TaskStatusId = 10   -- start
ORDER BY CreatedDate DESC
基本上,它为TaskConfigId分组TaskGuid,确保它有2个条目。对它进行排序,然后得到最后一个

我的问题是:如果我想确保这两个条目是10和20(如果我们可以确保顺序是先10,然后20,更好),该怎么办

我试过这个:

SELECT TOP (1) CreatedDate
FROM [aptfeed].[TaskTracking]
WHERE TaskGuid IN (
        SELECT TaskGuid
        FROM [aptfeed].[TaskTracking]
        WHERE TaskConfigId = 100
            AND (TaskStatusId = 10 OR TaskStatusId = 20)
        GROUP BY TaskGuid HAVING COUNT(*) = 2               
        )
    AND TaskStatusId = 10   -- start
ORDER BY CreatedDate DESC
但这不起作用,因为它首先过滤了所有其他TaskStatusId。因此,几乎所有计数(*)都将为2,即屏幕截图中的TaskConfigId=40将被选中,因为第14行将被过滤

另外,我觉得我使用的查询速度很慢,因为它必须为TaskConfigId对所有TaskGuid进行分组。有什么改进的建议吗


谢谢

您可以通过稍微调整原始查询来找到TaskGuid:

SELECT TaskGuid
FROM [aptfeed].[TaskTracking]
WHERE TaskConfigId = 100
GROUP BY TaskGuid
HAVING COUNT(*) = 2
AND    MIN(TaskStatusId) = 10
AND    MAX(TaskStatusId) = 20
这将解决查找包含10和20(不一定按该顺序)而不包含其他内容的组的问题

但您也可以使用窗口功能:

SELECT TaskConfigId, TaskGuid, MAX(CreatedDate)
FROM (
    SELECT TaskConfigId
         , TaskGuid
         , ItemCount = COUNT(*) OVER (PARTITION BY TaskConfigId, TaskGuid)
         , FirstStatus = FIRST_VALUE(TaskStatusId) OVER (PARTITION BY TaskConfigId, TaskGuid ORDER BY CreatedDate)
         , LastStatus = LAST_VALUE(TaskStatusId) OVER (PARTITION BY TaskConfigId, TaskGuid ORDER BY CreatedDate)
         , CreatedDate
    FROM [aptfeed].[TaskTracking]
) AS cte
WHERE ItemCount = 2
AND FirstStatus = 10
AND LastStatus = 20
GROUP BY TaskConfigId, TaskGuid

通过稍微调整原始查询,可以找到TaskGuid:

SELECT TaskGuid
FROM [aptfeed].[TaskTracking]
WHERE TaskConfigId = 100
GROUP BY TaskGuid
HAVING COUNT(*) = 2
AND    MIN(TaskStatusId) = 10
AND    MAX(TaskStatusId) = 20
这将解决查找包含10和20(不一定按该顺序)而不包含其他内容的组的问题

但您也可以使用窗口功能:

SELECT TaskConfigId, TaskGuid, MAX(CreatedDate)
FROM (
    SELECT TaskConfigId
         , TaskGuid
         , ItemCount = COUNT(*) OVER (PARTITION BY TaskConfigId, TaskGuid)
         , FirstStatus = FIRST_VALUE(TaskStatusId) OVER (PARTITION BY TaskConfigId, TaskGuid ORDER BY CreatedDate)
         , LastStatus = LAST_VALUE(TaskStatusId) OVER (PARTITION BY TaskConfigId, TaskGuid ORDER BY CreatedDate)
         , CreatedDate
    FROM [aptfeed].[TaskTracking]
) AS cte
WHERE ItemCount = 2
AND FirstStatus = 10
AND LastStatus = 20
GROUP BY TaskConfigId, TaskGuid

如果我没有弄错的话,您将尝试获取每个只有
TaskStatusId
10和20(这两个记录都应该存在)的
TaskConfigId
,并获取每个记录的最后一个
CreatedDate

你可以这样做:

SELECT *
FROM (
    SELECT *
    , COUNT(TaskGuid) OVER (PARTITION BY TaskGuid) TaskCount 
    , ROW_NUMBER() OVER (PARTITION BY TaskGuid ORDER BY CreatedDate DESC) RN    
    FROM 
        [aptfeed].[TaskTracking]
    WHERE 
        TaskConfigId = 100
    AND TaskStatusId IN(10,20)
) D
WHERE 
    TaskCount = 2
AND RN = 1

如果我没有弄错的话,您将尝试获取每个只有
TaskStatusId
10和20(这两个记录都应该存在)的
TaskConfigId
,并获取每个记录的最后一个
CreatedDate

你可以这样做:

SELECT *
FROM (
    SELECT *
    , COUNT(TaskGuid) OVER (PARTITION BY TaskGuid) TaskCount 
    , ROW_NUMBER() OVER (PARTITION BY TaskGuid ORDER BY CreatedDate DESC) RN    
    FROM 
        [aptfeed].[TaskTracking]
    WHERE 
        TaskConfigId = 100
    AND TaskStatusId IN(10,20)
) D
WHERE 
    TaskCount = 2
AND RN = 1

如果您试图获取TaskStatusId为10和20的每个TaskConfigId(两条记录都应该存在),并查找最后一个CreatedDate,请尝试以下操作:

SELECT TaskGuid
FROM [TaskTracking]
WHERE TaskConfigId = 100
AND (TaskStatusId = 10 OR TaskStatusId = 20)
GROUP BY TaskGuid HAVING COUNT(*) = 2  
如果需要,还可以显示日期:

SELECT TaskGuid, MAX(CreatedDate) AS LastDate
FROM [TaskTracking]
WHERE TaskConfigId = 100
AND (TaskStatusId = 10 OR TaskStatusId = 20)
GROUP BY TaskGuid HAVING COUNT(*) = 2  

如果您试图获取TaskStatusId为10和20的每个TaskConfigId(两条记录都应该存在),并查找最后一个CreatedDate,请尝试以下操作:

SELECT TaskGuid
FROM [TaskTracking]
WHERE TaskConfigId = 100
AND (TaskStatusId = 10 OR TaskStatusId = 20)
GROUP BY TaskGuid HAVING COUNT(*) = 2  
如果需要,还可以显示日期:

SELECT TaskGuid, MAX(CreatedDate) AS LastDate
FROM [TaskTracking]
WHERE TaskConfigId = 100
AND (TaskStatusId = 10 OR TaskStatusId = 20)
GROUP BY TaskGuid HAVING COUNT(*) = 2  

我真的不理解你试图实现的逻辑。我真的不理解你试图实现的逻辑。