【问题标题】:Calculate sum of maximum and minimum value for repeated group of entries in MySQL8计算MySQL8中重复条目组的最大值和最小值之和
【发布时间】:2021-04-02 02:27:14
【问题描述】:
LogDateAndTime BatchDate TagLetter Totaliser ExpectedResult
10-11-2020 09:06:14 10-11-2020 08:29:55 A 6319 31
10-11-2020 09:06:24 10-11-2020 08:29:55 A 6337 31
10-11-2020 09:08:14 10-11-2020 08:29:55 B 6355 31
10-11-2020 09:08:24 10-11-2020 08:29:55 B 6372 31
10-11-2020 09:08:34 10-11-2020 08:29:55 B 6378 31
10-11-2020 09:08:44 10-11-2020 08:29:55 A 6383 31
10-11-2020 09:09:14 10-11-2020 08:29:55 A 6388 31
10-11-2020 09:09:24 10-11-2020 08:29:55 A 6396 31
10-11-2020 09:09:34 10-11-2020 08:29:55 B 6409 31
10-11-2020 09:09:44 10-11-2020 08:29:55 B 6426 31
10-11-2020 09:10:24 10-11-2020 08:29:55 B 6442 31

上表有 LogDateAndTime(Primary_Key) 列,其中包含唯一的日期时间条目。 BatchDate 列在整个批次中保存相同的日期时间值。我需要为每个 TagLetter=A 实例计算 MAX(Totaliser)-MIN(Totaliser) 的总和,以便我应该忽略 TagLetter=B 中的值。在这种情况下,我的 ExpectedResult 将是 SUM[(6337-6319)+(6396-6383)]=31。我尝试了以下查询,但没有得到预期的结果。

SELECT SUM(
           CASE 
             WHEN TagLetter='A' THEN MAX(Totaliser)-MIN(Totaliser) 
             ELSE 0.0 
           END
          ) OVER (PARTITION BY BatchDate) AS ExpectedResult

在这种情况下,它正在计算 6396-6319=77,这不是预期的结果。有人可以帮我得到正确的结果吗?

【问题讨论】:

  • 你的 MySQL 版本是多少?
  • @ArunPalanisamy MySQL 8.0.22
  • 您不想在LogDateAndTime 上进行分区吗?批次日期都是一样的,所以我希望最终结果是 77
  • 实际上我看到 LogDateAndTime 中的所有日期都不同。你能解释一下你期望结果如何被划分吗?

标签: sum max window-functions min mysql-8.0


【解决方案1】:

考虑到您想要进行此计算BatchDate,下面是使用旧方法的解决方案。

with cte as (
select 
test.*, 
@rn := (if (@rt =TagLetter, @rn, @rn+1)) rank_,
@rt :=TagLetter
from test , (select @rn := 1,  @rt := '') t
)

select t1.*,t2.ExpectedResult from test t1
left join (
select  distinct BatchDate, sum(CASE 
             WHEN TagLetter='A' THEN MAX(Totaliser)-MIN(Totaliser) 
             ELSE 0.0 
           END) over ()
           AS ExpectedResult
          
          from cte
          
group by BatchDate,TagLetter,rank_) t2 on t1.BatchDate=t2.BatchDate

DEMO

【讨论】:

    【解决方案2】:

    首先使用窗口函数LAG()SUM() 创建连续的'A's 组,然后对这些组进行聚合:

    WITH cte AS (
      SELECT DISTINCT SUM(MAX(Totaliser) - MIN(Totaliser)) OVER () ExpectedResult
      FROM (
        SELECT *, SUM(flag) OVER (ORDER BY LogDateAndTime) grp
        FROM (
          SELECT *, LAG(TagLetter, 1, '') OVER (ORDER BY LogDateAndTime) <> 'A' flag
          FROM tablename 
        ) t
        WHERE TagLetter = 'A'
      ) t
      GROUP BY grp
    )
    SELECT t.*, c.ExpectedResult
    FROM tablename t CROSS JOIN cte c
    

    或者,如果您想要每个 BatchDate 的结果:

    WITH cte AS (
      SELECT DISTINCT BatchDate,
             SUM(MAX(Totaliser) - MIN(Totaliser)) OVER () ExpectedResult
      FROM (
        SELECT *, SUM(flag) OVER (PARTITION BY BatchDate ORDER BY LogDateAndTime) grp
        FROM (
          SELECT *, LAG(TagLetter, 1, '') OVER (PARTITION BY BatchDate ORDER BY LogDateAndTime) <> 'A' flag
          FROM tablename 
        ) t
        WHERE TagLetter = 'A'
      ) t
      GROUP BY BatchDate, grp
    )
    SELECT t.*, c.ExpectedResult
    FROM tablename t LEFT JOIN cte c
    ON c.BatchDate = t.BatchDate
    

    请参阅demo
    结果:

    > LogDateAndTime      | BatchDate           | TagLetter | Totaliser | ExpectedResult
    > :------------------ | :------------------ | :-------- | --------: | -------------:
    > 10-11-2020 09:06:14 | 10-11-2020 08:29:55 | A         |      6319 |             31
    > 10-11-2020 09:06:24 | 10-11-2020 08:29:55 | A         |      6337 |             31
    > 10-11-2020 09:08:14 | 10-11-2020 08:29:55 | B         |      6355 |             31
    > 10-11-2020 09:08:24 | 10-11-2020 08:29:55 | B         |      6372 |             31
    > 10-11-2020 09:08:34 | 10-11-2020 08:29:55 | B         |      6378 |             31
    > 10-11-2020 09:08:44 | 10-11-2020 08:29:55 | A         |      6383 |             31
    > 10-11-2020 09:09:14 | 10-11-2020 08:29:55 | A         |      6388 |             31
    > 10-11-2020 09:09:24 | 10-11-2020 08:29:55 | A         |      6396 |             31
    > 10-11-2020 09:09:34 | 10-11-2020 08:29:55 | B         |      6409 |             31
    > 10-11-2020 09:09:44 | 10-11-2020 08:29:55 | B         |      6426 |             31
    > 10-11-2020 09:10:24 | 10-11-2020 08:29:55 | B         |      6442 |             31
    

    【讨论】:

    • 感谢您的即时回复。您能否为每一行返回一个聚合值,即每行返回 31?
    • 谢谢你的帮助,forpas。
    • 在这行查询中,我想比较 C 和 A SELECT *, LAG(TagLetter, 1, '') OVER (PARTITION BY BatchDate ORDER BY LogDateAndTime) &lt;&gt; 'A' flag 如何比较 A 和 C? SELECT *, LAG(TagLetter, 1, '') OVER (PARTITION BY BatchDate ORDER BY LogDateAndTime) &lt;&gt; 'A' OR 'C' flag FROM tablename 给出的结果与上述查询相同。
    • @Midhunraj 如果您希望 LAG(TagLetter, 1, '') OVER (PARTITION BY BatchDate ORDER BY LogDateAndTime) 不等于“A”和“C”,请使用:LAG(TagLetter, 1, '') OVER (PARTITION BY BatchDate ORDER BY LogDateAndTime) NOT IN ('A', 'C')
    猜你喜欢
    • 2021-06-03
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 2015-10-29
    • 1970-01-01
    • 2015-12-03
    • 1970-01-01
    • 2013-11-11
    相关资源
    最近更新 更多