SQL:如何检查组中的值?

时间:2019-02-01 17:58:38

标签: sql sql-server group-by

我有一张这样的桌子:

enter image description here

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

因此,如果任务的状态为10 AND 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

基本上,它将TaskGuid分组为TaskConfigId,并确保它具有2个条目。对其进行排序,然后得到最后一个。

我的问题是:如果我想确保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。因此,几乎所有的COUNT(*)都将为2,即屏幕截图中的TaskConfigId = 40将被选中,因为第14行将被过滤。

此外,我觉得我正在使用的查询很慢,因为它必须将TaskConfigId的所有TaskGuid分组。有任何改善建议吗?

谢谢

3 个答案:

答案 0 :(得分:1)

您可以通过一点点调整原始查询来找到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

答案 1 :(得分: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  

答案 2 :(得分:0)

如果我做对了,那么您尝试获取的每个TaskConfigId分别为TaskStatusId 10和20(两个记录都应该存在),并获取最后一个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