Return ID 行匹配另一列中的最小值
Return ID row matching the minimum value in another column
目前这是我拥有的 -
select ServiceName, MethodName,
min(duration) AS duration, min(ID) as ID, count(id) As count
from dbo.log
group by ServiceName, MethodName
我需要返回的 ID 来匹配 min(duration)
值。目前我不确定它返回的是什么 ID,但它不是持续时间最短的 ID。
您应该尝试如下查询。该查询使用 Row_number() 但您也可以使用 rank() 以防您需要多行,以防许多记录具有相同的 minimum duration 。看到不错link on explanation
然而,下面的查询将 return 单行,而不管许多行对于相同的服务名称和方法名称具有相同的最短持续时间
select
ServiceName, MethodName,id,ct,duration
from
(
select *,
rn=row_number() over( partition by ServiceName, MethodName order by duration asc),
ct=count() over (partition by ServiceName, MethodName)
from dbo.log)t
where rn=1
只是添加一个不同的选项,我认为这个也应该有效:
with s as (
select ServiceName, MethodName,
min(duration) AS duration, count(id) As count
from dbo.log
group by ServiceName, MethodName
)
select s.*, l.id
from s
join dbo.log l on s.ServiceName = l.ServiceName
and s.Methodname = l.MethodName
and s.duration = l.duration;
如果有多行具有相同的最小值,则此查询将显示同一服务的多行。
如果您同时需要最短持续时间及其 ID,那么最简单的方法是使用两个 window 函数。
SELECT DISTINCT ServiceName, MethodName
, MIN(Duration) OVER (PARTITION BY ServiceName, MethodName ORDER BY Duration ASC)
, FIRST_VALUE(Id) OVER (PARTITION BY ServiceName, MethodName ORDER BY Duration ASC)
FROM log
似乎没有必要为持续时间的 MIN 使用 ORDER BY 子句,但是通过重用该分区,两个函数可以同时处理,而不必分成单独的集合并重新组合。最好的理解方法是取出 order by out 并查看查询计划,看看它是如何添加嵌套循环和许多其他额外步骤的。长话短说,这最终产生了一个非常简短而有效的计划。
我希望很明显如何检索到正确的 ID。基本上这依赖于这样一个事实,即对集合进行排序会导致第一行中的任何值与排序中使用的 min/max 个值相关。
如果多个 ID 与持续时间相匹配,并且您想查看所有 ID,则可以改为执行以下操作。您可以使用 TOP
将结果限制为特定行数。
SELECT l1.ServiceName, l1.MethodName, l1.Duration, x.Id
FROM (
SELECT ServiceName, MethodName, MIN(Duration) Duration
FROM log GROUP BY ServiceName, MethodName
) l1
CROSS APPLY (
SELECT TOP 10 Id
FROM log l2 WHERE l2.ServiceName = l1.ServiceName
AND l2.MethodName = l1.MethodName
AND l2.Duration = l1.Duration
) x
目前这是我拥有的 -
select ServiceName, MethodName,
min(duration) AS duration, min(ID) as ID, count(id) As count
from dbo.log
group by ServiceName, MethodName
我需要返回的 ID 来匹配 min(duration)
值。目前我不确定它返回的是什么 ID,但它不是持续时间最短的 ID。
您应该尝试如下查询。该查询使用 Row_number() 但您也可以使用 rank() 以防您需要多行,以防许多记录具有相同的 minimum duration 。看到不错link on explanation
然而,下面的查询将 return 单行,而不管许多行对于相同的服务名称和方法名称具有相同的最短持续时间
select
ServiceName, MethodName,id,ct,duration
from
(
select *,
rn=row_number() over( partition by ServiceName, MethodName order by duration asc),
ct=count() over (partition by ServiceName, MethodName)
from dbo.log)t
where rn=1
只是添加一个不同的选项,我认为这个也应该有效:
with s as (
select ServiceName, MethodName,
min(duration) AS duration, count(id) As count
from dbo.log
group by ServiceName, MethodName
)
select s.*, l.id
from s
join dbo.log l on s.ServiceName = l.ServiceName
and s.Methodname = l.MethodName
and s.duration = l.duration;
如果有多行具有相同的最小值,则此查询将显示同一服务的多行。
如果您同时需要最短持续时间及其 ID,那么最简单的方法是使用两个 window 函数。
SELECT DISTINCT ServiceName, MethodName
, MIN(Duration) OVER (PARTITION BY ServiceName, MethodName ORDER BY Duration ASC)
, FIRST_VALUE(Id) OVER (PARTITION BY ServiceName, MethodName ORDER BY Duration ASC)
FROM log
似乎没有必要为持续时间的 MIN 使用 ORDER BY 子句,但是通过重用该分区,两个函数可以同时处理,而不必分成单独的集合并重新组合。最好的理解方法是取出 order by out 并查看查询计划,看看它是如何添加嵌套循环和许多其他额外步骤的。长话短说,这最终产生了一个非常简短而有效的计划。
我希望很明显如何检索到正确的 ID。基本上这依赖于这样一个事实,即对集合进行排序会导致第一行中的任何值与排序中使用的 min/max 个值相关。
如果多个 ID 与持续时间相匹配,并且您想查看所有 ID,则可以改为执行以下操作。您可以使用 TOP
将结果限制为特定行数。
SELECT l1.ServiceName, l1.MethodName, l1.Duration, x.Id
FROM (
SELECT ServiceName, MethodName, MIN(Duration) Duration
FROM log GROUP BY ServiceName, MethodName
) l1
CROSS APPLY (
SELECT TOP 10 Id
FROM log l2 WHERE l2.ServiceName = l1.ServiceName
AND l2.MethodName = l1.MethodName
AND l2.Duration = l1.Duration
) x