SQL中如何使用over-partition by query获取当前值、平均值和最大值?

Posted

技术标签:

【中文标题】SQL中如何使用over-partition by query获取当前值、平均值和最大值?【英文标题】:How to use over - partition by query in SQL in order to get the current, average, and maximum value? 【发布时间】:2021-03-03 07:30:51 【问题描述】:

我有这张表,它显示了设备在某个区域和特定位置所做的点。

working_date    device   points   area   location
19-06-2020        a        1       x       xa   
19-06-2020        a        2       x       xa 
19-06-2020        a        3       x       xa 
19-06-2020        a        4       x       xa
20-06-2020        a        5       x       xa
20-06-2020        a        6       x       xa
20-06-2020        a        7       x       xa
20-06-2020        a        8       x       xa
20-06-2020        a        9       x       xa

我想获取按区域和位置分组的当前点、平均点和最大点。如果我选择任何一天,当前数量将显示最近工作日期的数量。同时,平均数量将显示设备工作的总体平均值。最后,最大数量将显示设备完成的整体最大点。

根据我上面的表格,如果我选择 21-06-2020 那么想要的结果:

working_date  area  location   device   current_qty  avg_qty   max_qty
21-06-2020     x       xa        a         5           4,5        5

平均数量来自total_qty / total_of_date,而最大数量来自所有日期的最大数量。

到目前为止我构建的查询是:

select t1.working_date, t1.device, t1.area, t1.location, t1.points_qty, t1.total_date,
sum(t1.pile_qty) over(partition by t1.working_date) / sum(t1.total_date) over(partition by t1.working_date) as avg_qty,
max(t1.pile_qty) over(partition by t1.working_date) as max_qty
from (
select working_date, device, points, area, location, count(points) as points_qty, count(distinct working_date) as total_date 
from table1 group by device, area, location
group by working_date, device, points, area, location) t1
group by working_date, device, points, area, location, pile_qty, total_date

通过上面的查询,我得到:

working_date  area  location   device   current_qty  avg_qty   max_qty
21-06-2020     x       xa        a         5           5          5

我应该如何编写查询以获得所需的结果?

提前致谢。

【问题讨论】:

您想要的输出显示 21 日,这在示例数据中不可用。所以计算出来的数据很难看懂…… 意思是,如果我选择任何一天,想要的结果总是给我最新的working_date 数量值从何而来? 通过点数 我不知道 PostgreSQL,但是在 MS SQL Server 中聚合函数返回与聚合列相同的数据类型;我建议使用sum(...) * 1.0 / sum(...) 【参考方案1】:

我想,我有你的解决方案。但是,我不确定答案是否会在不同情况下提供正确的结果。下面是我的代码=> 请检查链接=>DB-FIDDLE LINK。

WITH CTE AS
    (
      SELECT working_date,area,location,device, 
             COUNT(working_date) GrpCount
      FROM MYTable 
      GROUP BY working_date,area,location,device
    
    ),y AS
    (SELECT area,location,device,GrpCount,
           (SELECT GrpCount FROM CTE WHERE working_date<TO_DATE('21-06-2020','DD-MM-YYYY') ORDER BY working_date DESC LIMIT 1)  current_qty  
    FROM CTE
    )
    SELECT TO_DATE('21-06-2020','DD-MM-YYYY'),area,location,device, 
           MAX(current_qty) current_qty,
           string_agg(GrpCount::text, ',') avg_qty,
           Max(GrpCount) max_qty
    FROM Y
    GROUP BY area,location,device

注意:-在这里,您可以看到,对于current_qty,我已使用您输入的日期21-06-2020(SELECT GrpCount FROM CTE WHERE working_date&lt;TO_DATE('21-06-2020','DD-MM-YYYY') ORDER BY working_date DESC LIMIT 1) current_qty 来查找当前数量。它给了我你的预期结果。请检查具有不同日期范围和数据范围的代码。

【讨论】:

【参考方案2】:

demo:db<>fiddle

SELECT
    *,
    AVG(current_qty) OVER () as avg_qty,             -- 2
    MAX(current_qty) OVER () as max_qty
FROM (
    SELECT 
        working_date,
        area,
        location,
        device,
        COUNT(*) as current_qty                      -- 1
    FROM mytable
    GROUP BY working_date, device, area, location    -- 1
) s
WHERE working_date <= '2020-06-21'                   -- 3
ORDER BY working_date DESC
LIMIT 1
    working_date 值进行普通分组以计算日期的qty 值。 使用整个分组数据集的这些 qty 值将 avgmax 数量值添加到使用无限窗口函数的记录中 要查找给定日期的最新数据集:过滤具有相同或较小日期值的所有记录,将这些日期中最近的日期排在最前面,并使用限制仅返回最前面的日期。

仅当您的区域、位置和设备值与示例中的每条记录相同时,分组才能正常工作。如果它们不同,您可以使用COUNT() 作为窗口函数而不是组聚合来将值添加到每条记录:

demo:db<>fiddle

SELECT
    *,
    AVG(current_qty) OVER () as avg_qty,
    MAX(current_qty) OVER () as max_qty
FROM (
    SELECT 
        working_date,
        area,
        location,
        device,
        COUNT(*) OVER (PARTITION BY working_date) as current_qty
    FROM mytable
) s
WHERE working_date <= '2020-06-21'
ORDER BY working_date DESC
LIMIT 1

但是,在这种情况下,不清楚应该提取2020-06-20 组的五条记录中的哪一条。您必须应用您的订单标准才能将预期的订单排在最前面。

【讨论】:

这些答案有帮助吗?那么请不要忘记UPVOTE他们!如果一个答案完全解决了您的问题,请不要忘记另外接受它以关闭问题。

以上是关于SQL中如何使用over-partition by query获取当前值、平均值和最大值?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SQL 中使用 group by 运行 sum?

如何使用 ORDER BY 在 SQL/MySQL 中查找行

如何在 T-SQL 中使用 group by 和 union

如何在 SQL 中不使用“ORDER BY”进行升序排序

如何在没有算术计数的SQL子查询中使用GROUP BY

使用 group by 和 like 语句时如何让 SQL 使用 where 条件