SQL:如何检查组内的值?
我有一张这样的桌子: 对于每个TaskConfigId,都有一个TaskGuid。如果同一TaskConfigId的TaskGuid相同,则它们似乎用于同一任务。通常,TaskStatusId为10或20。当发生某些事情时,TaskStatusId将是其他值,即15。但对于每个任务,它总是有10和20个 因此,如果任务的状态为10和20,则表示没有发生任何特殊情况 现在,我想了解TaskConfigId(例如100)的最后一个CreatedDate是什么时候,它只有TaskStatusId 10和20,没有其他值。因此,如果TaskConfigId为40,则突出显示的大小写不正确 这是我的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
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
我真的不理解你试图实现的逻辑。我真的不理解你试图实现的逻辑。