返回与另一列中的最小值匹配的 ID 行 [重复]

Posted

技术标签:

【中文标题】返回与另一列中的最小值匹配的 ID 行 [重复]【英文标题】:Return ID row matching the minimum value in another column [duplicate] 【发布时间】:2018-11-10 19:57:26 【问题描述】:

目前这就是我所拥有的 -

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,但它不是持续时间最短的那个。

【问题讨论】:

如果多行具有相同的“最小值”值,您想要什么?你选哪一个? 【参考方案1】:

如果您同时需要最小持续时间及其 id,那么最简单的方法是使用两个窗口函数。

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 子句,但是通过重用该分区,两个函数可以同时处理,而不必分成​​单独的集合并重新组合。最好的理解方法是按顺序排列并查看查询计划,看看它是如何添加嵌套循环和许多其他额外步骤的。长话短说,这最终会产生一个非常简短而有效的计划。

我希望如何检索正确的 ID 是显而易见的。基本上,这依赖于这样一个事实,即对集合进行排序会导致第一行中的任何值都与排序中使用的最小/最大值相关。

如果多个 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

【讨论】:

这实际上正是我所需要的。谢谢,只返回一个值(最低),不管是哪个值。 有没有办法不使用 FIRST_VALUE 来获得前 10 个值? 您想要最多 10 个匹配相同持续时间的 ID 吗?如果是这样,我修改了我的答案以支持这一点【参考方案2】:

只是添加一个不同的选项,我认为这个应该也可以工作:

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;

如果有多行具有相同的最小值,此查询将显示同一服务的多行。

【讨论】:

这适用于多个持续时间最短的实例。 是的,这就是我一直在说的。【参考方案3】:

您应该尝试如下查询。该查询使用 Row_number() 但您也可以使用 rank() 以防您需要多行,以防许多记录具有相同的最小持续时间。看到一个不错的link on explanation

然而,下面的查询将返回单行,而不管对于相同的服务名称和方法名称具有相同最短持续时间的许多行

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

【讨论】:

以上是关于返回与另一列中的最小值匹配的 ID 行 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

仅返回一列中的日期与另一列中的日期最接近的行?

返回值的公式,其中一列中的第一个单词与另一列的最后四位匹配

在python中,我如何对一列中每个值与另一列中的值发生的次数(多少行)建立矩阵?

将一列中的文本与另一列匹配(vlookup + like)

使用 PySpark 连接与另一列中的两列确定的范围相匹配的数据框

根据与另一列的部分匹配创建新列