当前位置: 首页 > 面试题库 >

TSQL分组时选择“最小和最大”行

陈浩
2023-03-14
问题内容

可以说我有一个包含许多这样的行的表:

ID        Range         Range_begining        Profit
----------------------------------------------------
 1    (100-150)                    100           -20
 2    (200-250)                    200          40.2
 3    (100-150)                    100           100
 4    (450-500)                    450           -90
 ...

我正在做一个简单的查询,像这样:

SELECT max([Range]) AS 'Range'
     , count(ID) AS 'Count'
     , round(avg([Profit]), 2) AS 'AVG Profit'
    FROM
        Orders
    GROUP BY
        Range_begining

运行此查询后,我得到如下结果:

Range        Count        AVG Profit
------------------------------------
(100-150)        2                40
(200-250)        1              40.2
(450-500)        1               -90
 ...

非常简单 :)

我现在需要做的是选择计数大于10的具有最小和最大利润的行(这是一个参数)

我能够通过此获得最小值:

SELECT TOP 1 [Range], [AVG Profit] FROM (
     SELECT max([Range]) AS 'Range'
         , count(ID) AS 'Count'
         , round(avg([Profit]), 2) AS 'AVG Profit'
        FROM
            Orders
        GROUP BY
            Range_begining) X
WHERE
    [Count]>10
ORDER BY 
    [AVG Profit] ASC --or DESC if I want max profit

我正在考虑UNION使用ORDER BY DESC进行上述查询,但这不是最佳解决方案。

我需要做的是:
选择2行:按范围分组时,第一行最少,第二行最大AVG利润。

编辑: 如果我这样向我的主数据表中添加2移动列:

ID        Range         Range_begining        Profit        OrderDate     Company
---------------------------------------------------------------------------------
 1    (100-150)                    100           -20        2012-01-02          1
 2    (200-250)                    200          40.2        2012-03-22          0
 3    (100-150)                    100           100        2012-02-05          0
 4    (450-500)                    450           -90        2012-05-12          1
 ...

然后尝试再添加2个这样的条件:

; with ordering as (
  SELECT max([Range]) AS 'Range'
     , count(ID) AS 'Count'
     , round(avg([Profit]), 2) AS 'AVG Profit'
     , row_number() over (order by avg([Profit])) rn_min
     , row_number() over (order by avg([Profit]) desc) rn_max
    FROM
        Orders
    GROUP BY
        Range_begining
    HAVING COUNT(ID) > 10
    AND [Company]=@company
    AND (@from= '' OR [OrderDate]>=@from)
    AND (@to= '' OR [OrderDate]<=@to)
)
select [range], [count], [avg profit]
  from ordering
 where (rn_max = 1 or rn_min = 1)

我收到错误消息是因为[公司]和[订单日期]

在HAVING子句中无效,因为它不在聚合函数或GROUP BY子句中。

我怎样才能解决这个问题?

EDIT2 可以使用了!

; with ordering as (
  SELECT max([Range]) AS 'Range'
     , count(ID) AS 'Count'
     , round(avg([Profit]), 2) AS 'AVG Profit'
     , row_number() over (order by avg([Profit])) rn_min
     , row_number() over (order by avg([Profit]) desc) rn_max
    FROM
        Orders
    WHERE
    [Company]=@company
    AND (@from= '' OR [OrderDate]>=@from)
    AND (@to= '' OR [OrderDate]<=@to)
    GROUP BY
        Range_begining
    HAVING COUNT(ID) > 10
)
select [range], [count], [avg profit]
  from ordering
 where (rn_max = 1 or rn_min = 1)

编辑3 我可以返回另一个描述如下的列:

Range        AVG Profit               Description
-------------------------------------------------
(200-250)          40.2           Max profit here
(450-500)           -90     Min profit, well done

编辑4 快速答案(基于@Nikola Markovinovi膰答案):

; with ordering as (
  SELECT max([Range]) AS 'Range'
     , count(ID) AS 'Count'
     , round(avg([Profit]), 2) AS 'AVG Profit'
     , row_number() over (order by avg([Profit])) rn_min
     , row_number() over (order by avg([Profit]) desc) rn_max
    FROM
        Orders
    WHERE
    [Company]=@company
    AND (@from= '' OR [OrderDate]>=@from)
    AND (@to= '' OR [OrderDate]<=@to)
    GROUP BY
        Range_begining
    HAVING COUNT(ID) > 10
)
    SELECT
    CASE WHEN rn_max=1 THEN 'This is max' ELSE 'Min' END AS 'Description'
    ,[range]
    ,[count]
    ,[avg profit]
    FROM ordering
    WHERE (rn_max = 1 or rn_min = 1)

问题答案:

您可以使用窗口功能一次完成此操作:

; with ordering as (
  SELECT max([Range]) AS 'Range'
     , count(ID) AS 'Count'
     , round(avg([Profit]), 2) AS 'AVG Profit'
     , row_number() over (order by avg([Profit])) rn_min
     , row_number() over (order by avg([Profit]) desc) rn_max
    FROM
        Orders
    GROUP BY
        Range_begining
    HAVING COUNT(ID) > 10
)
select [range], [count], [avg profit],
       case when rn_max = 1 
            then 'Max profit'
            else 'Min profit'
        end Description
  from ordering
 where (rn_max = 1 or rn_min = 1)


 类似资料:
  • 问题内容: 我正在尝试制作类似提醒的应用程序。我想允许用户选择不是现在(至少从现在起5分钟)的日期和时间,并且我也想禁止用户选择距离太远的日期- 例如30天。我创建了datePicker和timePicker,使它们在单击按钮时弹出,但是找不到设置最小值和最大值的方法。 问题答案: 试试这个: 但是,您需要检查用户是否选择了今天的日期,并且时间是否小于当前时间条件。

  • 问题内容: 我试图一次从一张桌子上得到2行。上周的最小日期时间(今天-7)和最晚的日期(今天)的一个。 我的桌子: 我可以通过以下方式选择上周的数据: 但我只想要第1行和第125行,因为这些是用于计算的行。所以我的问题是: 如何从上一个查询的结果中选择2行(带有MIN和MAX日期)? 问题答案: 您可以使用此: 编辑: 由于两台计算机完全有可能具有相同的值,因此应更新查询以在子句中也包含过滤器。我

  • 问题内容: 如果要从整个表中选择最小值和最大值,则可以使用以下方法: 但是,如何仅从表的一部分中选择最小值和最大值?例如,我在一个表中有30行。我想从前十行中选择最小值和最大值,然后从后十行中选择,然后形成最后的10行。 我已经尝试过类似的东西 但这没有用。 如何用最少的查询解决此问题? 问题答案: 此外,MySQL具有一项很酷的功能,可让您返回任意范围的行(例如,返回10-20行)。这对于显示记

  • 问题内容: 我已经看到了很多解决此类问题的解决方案尤其是此SQL仅选择在Column上具有Max Value的行,但是似乎没有一个合适的解决方案: 我有以下表格布局,即附件的版本控制,这些附件绑定到实体: 输出应该是最大版本号,按group_id和Entity_id分组,如果有帮助,我只需要一个单个entity_id的列表即可: 我想出的是这种自我加入: 但是,只有在不同的实体不共享相同的组号的情

  • 问题内容: 我有包含以下字段的表: 如何创建SQL,请选择按ID,DATE_FROM,DATE_TO对结果进行分组并从价格中选择最低的值。 所以结果是 问题答案:

  • 主要内容:普通算法,分治算法程序中,我们经常使用数组(列表)存储给定的线性序列(例如 {1,2,3,4}),那么如何查找数组(序列)中的最大值或者最小值呢? 查找数组(序列)中最大值或最小值的算法有很多,接下来我们以 {3,7,2,1} 序列为例讲解两种查找最值的算法,一种是普通算法,另一种是借助 分治算法解决。 普通算法 普通算法的解决思路是:创建两个变量 max 和 min 分别记录数组中的最大值和最小值,它们的初始值都