最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

How to get difference value (delta) between to rows after query in Mariadb - Stack Overflow

programmeradmin4浏览0评论

Helo, this is my query:

MariaDB [PV_Anlage]>

SELECT created_at, verbrauch_ges 
FROM pv_metrics 
group by DATE(created_at) 
ORDER BY ID DESC limit 20;
+---------------------+---------------+
| created_at          | verbrauch_ges |
+---------------------+---------------+
| 2025-03-23 00:00:04 |       5628.79 |
| 2025-03-22 00:00:06 |       5622.54 |
| 2025-03-21 00:00:11 |       5615.44 |
| 2025-03-20 00:00:13 |       5609.49 |
| 2025-03-19 00:00:17 |        5605.4 |
| 2025-03-18 00:00:00 |       5600.45 |
| 2025-03-17 00:00:03 |       5591.36 |
| 2025-03-16 00:00:09 |        5585.2 |
| 2025-03-15 00:00:16 |       5578.96 |
| 2025-03-14 00:00:04 |        5571.1 |
| 2025-03-13 00:00:07 |       5560.34 |
| 2025-03-12 00:00:10 |       5550.54 |
| 2025-03-11 00:00:13 |       5540.12 |
| 2025-03-10 00:00:16 |       5534.81 |
| 2025-03-09 00:00:18 |       5528.48 |
| 2025-03-08 00:00:17 |       5521.71 |
| 2025-03-07 00:00:11 |       5515.27 |
| 2025-03-06 00:00:14 |       5510.17 |
| 2025-03-05 00:00:06 |       5504.08 |
| 2025-03-04 00:00:09 |       5497.21 |
+---------------------+---------------+

This is the result, as I'm writing values every 20sec. I've selected the very firste value of the day, so now I need the diffrence between the days. I've tried with LAG() function but I dont understand how to include the function into the general query.

best regardas Frank

Helo, this is my query:

MariaDB [PV_Anlage]>

SELECT created_at, verbrauch_ges 
FROM pv_metrics 
group by DATE(created_at) 
ORDER BY ID DESC limit 20;
+---------------------+---------------+
| created_at          | verbrauch_ges |
+---------------------+---------------+
| 2025-03-23 00:00:04 |       5628.79 |
| 2025-03-22 00:00:06 |       5622.54 |
| 2025-03-21 00:00:11 |       5615.44 |
| 2025-03-20 00:00:13 |       5609.49 |
| 2025-03-19 00:00:17 |        5605.4 |
| 2025-03-18 00:00:00 |       5600.45 |
| 2025-03-17 00:00:03 |       5591.36 |
| 2025-03-16 00:00:09 |        5585.2 |
| 2025-03-15 00:00:16 |       5578.96 |
| 2025-03-14 00:00:04 |        5571.1 |
| 2025-03-13 00:00:07 |       5560.34 |
| 2025-03-12 00:00:10 |       5550.54 |
| 2025-03-11 00:00:13 |       5540.12 |
| 2025-03-10 00:00:16 |       5534.81 |
| 2025-03-09 00:00:18 |       5528.48 |
| 2025-03-08 00:00:17 |       5521.71 |
| 2025-03-07 00:00:11 |       5515.27 |
| 2025-03-06 00:00:14 |       5510.17 |
| 2025-03-05 00:00:06 |       5504.08 |
| 2025-03-04 00:00:09 |       5497.21 |
+---------------------+---------------+

This is the result, as I'm writing values every 20sec. I've selected the very firste value of the day, so now I need the diffrence between the days. I've tried with LAG() function but I dont understand how to include the function into the general query.

best regardas Frank

Share Improve this question edited Mar 23 at 17:58 ValNik 6,2191 gold badge7 silver badges15 bronze badges asked Mar 23 at 16:31 DB5FPDB5FP 233 bronze badges 1
  • The query is illogical. It contains incomplete grouping. Enable ONLY_FULL_GROUP_BY then fix your query. – Akina Commented Mar 23 at 17:47
Add a comment  | 

3 Answers 3

Reset to default 0

In simple case,
if we consider the value of verbrauch_ges to be monotonously increasing, the smallest (initial) value for the day can be obtained as follows

SELECT min(created_at)created_at
  ,min(verbrauch_ges) verbrauch_ges
  ,lag(min(verbrauch_ges))over(order by created_at) prev_verbauch_ges
  ,min(verbrauch_ges)-coalesce(lag(min(verbrauch_ges))over(order by created_at),0.0) as day_diff
FROM pv_metrics 
group by DATE(created_at) 
ORDER BY ID DESC limit 20;

for LAG function we use value min(verbrauch_ges) because LAG function in SELECT clause will be executed after GROUP BY.
This is semantically equivalent to

SELECT created_at, verbrauch_ges
  ,lag(verbrauch_ges)over(order by created_at) prev_verbauch_ges
FROM (
  SELECT min(created_at) as created_at, min(verbrauch_ges) as verbrauch_ges
  FROM pv_metrics 
  group by DATE(created_at) 
  ORDER BY ID DESC limit 20
)sq
;

MariaDb allows use order by created_at and order by date(created_at) in LAG function.

Common case is select target rows from table and INNER JOIN table to this selection

SELECT created_at, verbrauch_ges
  ,lag(verbrauch_ges)over(order by created_at) prev_verbauch_ges
FROM (
   select min(id) id
   from pv_metrics  
   group by DATE(created_at)
   ORDER BY min(id) DESC limit 20
) s
inner join pv_metrics m on m.id=s.id
ORDER BY s.ID DESC ;

OR

SELECT created_at, verbrauch_ges
  ,lag(verbrauch_ges)over(order by created_at) prev_verbauch_ges
FROM (
   select min(created_at) created_at
   from pv_metrics  
   group by DATE(created_at)
   ORDER BY min(id) DESC limit 20
) s
inner join pv_metrics m on m.created_at=s.created_at
ORDER BY s.ID DESC ;

Examples

Your query exploits the notorious MySQL extension to GROUP BY. It means this baffling pile of uncertainty.

SELECT created_at, ANY_VALUE(verbrauch_ges)
  FROM pv_metrics
 group by DATE(created_at)
 ORDER BY ANY_VALUE(ID) DESC limit 20

ANY_VALUE)_ tells MySQL it can arbitrarily choose some value from the group. You get unpredictable values from that.

This makes it hard to guess your intent from your example.

It sounds like you want a result set with one row per calendar day, showing the difference between the verbrauch_ges values with the earliest created_at datestamp for that day

Here's how you do that.

First you want a result set with the earliest created_at time on each day.

SELECT MIN(created_at) created_at
  FROM pv_metrics
 GROUP BY DATE(created_at)

Then you want to extract the values, one per day.

SELECT DATE(pv_metrics.created_at) tag, AVG(verbracht_ges) erste_verbraucht_ges 
  FROM pv_metrics
  JOIN (
        SELECT MIN(created_at) created_at
         FROM pv_metrics
        GROUP BY DATE(created_at)
       ) firsts ON pv_metrics.created_at = firsts.created_at
  GROUP_BY DATE(pv_metrics.created_at) 

The AVG() is there to do something reasonable if you have more than one observation at precisely the same created_at time. You could also use MAX() or MIN().

Finally, now that you have a virtual table with columns tag and erste_verbraucht_ges you can do a LAG select on it to get your desired result.

created_at verbrauch_ges prev_verbauch_ges day_diff
2025-03-23 00:00:04 5628.79 5622.54345703125 6.2431640625
2025-03-22 00:00:06 5622.54 5615.43798828125 7.10546875
2025-03-21 00:00:11 5615.44 5609.4912109375 5.94677734375
2025-03-20 00:00:13 5609.49 5605.40380859375 4.08740234375
2025-03-19 00:00:17 5605.4 5600.44970703125 4.9541015625
2025-03-18 00:00:00 5600.45 5591.36279296875 9.0869140625
2025-03-17 00:00:03 5591.36 5585.2001953125 6.16259765625
2025-03-16 00:00:09 5585.2 5578.9580078125 6.2421875
2025-03-15 00:00:16 5578.96 5571.10498046875 7.85302734375
2025-03-14 00:00:04 5571.1 5560.3427734375 10.76220703125
2025-03-13 00:00:07 5560.34 5550.5400390625 9.802734375
2025-03-12 00:00:10 5550.54 5540.1171875 10.4228515625
2025-03-11 00:00:13 5540.12 5534.80908203125 5.30810546875
2025-03-10 00:00:16 5534.81 5528.48046875 6.32861328125
2025-03-09 00:00:18 5528.48 5521.70703125 6.7734375
2025-03-08 00:00:17 5521.71 5515.27392578125 6.43310546875
2025-03-07 00:00:11 5515.27 5510.17431640625 5.099609375
2025-03-06 00:00:14 5510.17 5504.083984375 6.09033203125
2025-03-05 00:00:06 5504.08 5497.21240234375 6.87158203125
2025-03-04 00:00:09 5497.21 5489.51904296875 7.693359375
SELECT min(created_at)created_at
  ,min(verbrauch_ges) verbrauch_ges
  ,lag(min(verbrauch_ges))over(order by created_at) prev_verbauch_ges
  ,min(verbrauch_ges)-coalesce(lag(min(verbrauch_ges))over(order by created_at),0.0) as day_diff
FROM pv_metrics 
group by DATE(created_at) 
ORDER BY ID DESC limit 20;

That's the answer or query I've needed.

Thanks

发布评论

评论列表(0)

  1. 暂无评论