简体   繁体   English

按年份显示 SUM 和 LAST_VALUE 组

[英]Display SUM and LAST_VALUE groups by Year

Last forum I made question how to display values following max date, but I want to sum some values group by max date unfortunately a single value didn't want follow max date.上一个论坛我提出了如何在最大日期之后显示值的问题,但我想按最大日期对一些值进行求和,不幸的是单个值不想遵循最大日期。

Here was my table:这是我的桌子:

桌子

And my query:我的查询:

SELECT
    SUM(pembelian) AS Buying,
    SUM(penjualan) AS Selling, 
    SUM(penjualan)-SUM(pembelian) AS Benefit, 
    saldo, 
    MAX(tgl_lap) 
FROM laporan GROUP BY DATE_FORMAT(tgl_lap,'%Y')

The results:结果:

在此处输入图像描述

As we saw it, the results does work for some values but a single value ( saldo ) didn't following max date, guys can see the row of 2020 should be '23581800' and 2021 should be '35639800' according table.正如我们所看到的,结果确实适用于某些值,但单个值 ( saldo ) 没有遵循最大日期,根据表格,大家可以看到 2020 年的行应该是“23581800”,2021 年应该是“35639800”。 So what I have missed?那我错过了什么?

Because of MySQL mode ONLY_FULL_GROUP_BY is disabled I think your query is not throwing error even though you have used non aggregated column saldo in the select clause.由于MySQL模式ONLY_FULL_GROUP_BY被禁用,我认为即使您在 select 子句中使用了非聚合列saldo ,您的查询也不会抛出错误。

Update after Clarification from OP OP澄清后更新

Another alternative to use window function first_value for saldo if you can,如果可以的话,另一种使用 window saldo first_value的方法,

select sum(pembelian) as Buying,
       sum(penjualan) as Selling, 
       sum(penjualan)-sum(pembelian) as Benefit, 
       max(saldo) as Saldo,
       max(tgl_lap) as tgl_lap
from
( select id_lap,pembelian,penjualan,tgl_lap,
         first_value(saldo) over 
         (partition by date_format(tgl_lap,'%Y') order by tgl_lap desc) as saldo
   from laporan
) l
group by date_format(tgl_lap,'%Y')

I mean next query can solve the problem:我的意思是下一个查询可以解决问题:

SELECT Buying, Selling, Benefit, saldo, last_tgl_lap
FROM laporan
JOIN (
  SELECT
    SUM(pembelian) AS Buying,
    SUM(penjualan) AS Selling, 
    SUM(penjualan)-SUM(pembelian) AS Benefit, 
    MAX(tgl_lap) last_tgl_lap
  FROM laporan 
  GROUP BY YEAR(tgl_lap)
) aggregated on aggregated.last_tgl_lap = tgl_lap;

Look here the example SQLize.online看这里的例子SQLize.online

If your MySQL version is 8.0 or greater you can use window function like:如果您的 MySQL 版本是 8.0 或更高版本,您可以像这样使用 window function:

SELECT 
    Pembelian AS Buying,
    Penjualan AS Selling,
    Penjualan - Pembelian AS Benefit,
    Saldo,
    LastDate
FROM (
  SELECT
    SUM(pembelian) OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap ASC) AS Pembelian,
    SUM(penjualan) OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap ASC) AS Penjualan,
    LAST_VALUE(saldo) OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap ASC) AS Saldo,
    LAST_VALUE(tgl_lap) OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap ASC) AS LastDate,
    ROW_NUMBER() OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap DESC) AS row_num
  FROM laporan
) tbl
WHERE row_num = 1;

Fiddle on SQLize.online Fiddle on SQLize.online

Your query is malformed.您的查询格式不正确。 You have saldo in the SELECT , but it is not in the GROUP BY .您在saldo中有SELECT ,但它不在GROUP BY中。 You should be getting an error.你应该得到一个错误。 An MySQL finally conforms to the SQL standard and to other databases in generating an error.一个MySQL终于符合SQL标准和其他数据库报错。

In MySQL 8.0, I would recommend conditional aggregation:在MySQL 8.0,我会推荐条件聚合:

SELECT SUM(pembelian) AS Buying, SUM(penjualan) AS Selling, 
       SUM(penjualan)-SUM(pembelian) AS Benefit, 
       MAX(CASE WHEN seqnum = 1 THEN saldo END) as saldo,
       MAX(tgl_lap) 
FROM (SELECT l.*,
             ROW_NUMBER() OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap DESC) as seqnum
      FROM laporan l
     ) l
GROUP BY YEAR(tgl_lap);

Note that I replaced DATE_FORMAT() with YEAR() .请注意,我将DATE_FORMAT()替换为YEAR() It just seems clearer to me to use the appropriate date function when it is available.在可用时使用适当的date function 对我来说似乎更清楚。

In older versions, there is a hack to get the latest saldo value in each year:在旧版本中,有一个 hack 可以获取每年最新的saldo值:

SELECT SUM(pembelian) AS Buying, SUM(penjualan) AS Selling, 
       SUM(penjualan)-SUM(pembelian) AS Benefit, 
       SUBSTRING_INDEX(GROUP_CONCAT(saldo ORDER BY tgl_lap DESC), ',', 1) + 0 as saldo,
       MAX(tgl_lap) 
FROM laporan l
GROUP BY YEAR(tgl_lap);

This concatenates the saldo values into a string and then takes the first element.saldo值连接成一个字符串,然后获取第一个元素。 The only caveat is that the default internal length is about 1,000 characters for GROUP_CONCAT() .唯一需要注意的是GROUP_CONCAT()的默认内部长度约为 1,000 个字符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM