简体   繁体   English

mysql:一列中值的差异

[英]mysql: difference between values in one column

this board helped me a few times in the past. 这个董事会过去曾帮我几次。

My challange: I want to get the difference between the values within one column. 我的挑战:我希望得到一列内的值之间的差异。

The table looks like this: 该表如下所示:

id  |  channel_id  |  timestamp   |  value
4515|    7         |1519771680000 |  7777
4518|    8         |1519772160000 |  6666
4520|    7         |1519772340000 |  8888
  • id: Internal ID from Datasource. id:Datasource的内部ID。 In some cases it's ordered, in other cases not. 在某些情况下,它是有序的,在其他情况下则没有。 We cannot thrust this order. 我们不能推动这个命令。
  • channel_id: Different data sources. channel_id:不同的数据源。
  • timestamp: unix timestamp. timestamp:unix时间戳。
  • value: measured value. 值:测量值。

What I want to do: 我想做的事:

Filter (eg channel_id = 7). 过滤(例如channel_id = 7)。 Calculate the difference between one timestamp and the next one. 计算一个时间戳和下一个时间戳之间的差异。 In this example: 8888-7777 在此示例中:8888-7777

I found an solution on another database but I cannot transfer it to mysql as the windows functions are very limited. 我在另一个数据库上找到了一个解决方案但我无法将其转移到mysql,因为windows函数非常有限。 Has somebody of you an idea how to get a solution which can be used in select statements? 有人想知道如何获得可以在select语句中使用的解决方案吗?

Thx and KR Holger Thx和KR Holger

You can get the two rows to compare (ie subtract) by joining the table to itself: 您可以通过将表连接到自身来获取要比较(即减去)的两行:

SELECT
    a.channel_id,
    a.timestamp,
    b.timestamp,
    a.value - b.value as `difference`
FROM table a
JOIN table b
ON a.channel_id = b.channel_id and a.timestamp <> b.timestamp and a.value > b.value
GROUP BY a.channel_id
ORDER BY a.channel_id

You can use a "correlated subquery" for this as seen below (also see this demo) . 您可以使用“相关子查询”,如下所示(另请参阅此演示) When MySQL implements window functions such a LEAD() you could use those instead. 当MySQL实现LEAD()这样的窗口函数时,你可以使用它们。

MySQL 5.6 Schema Setup : MySQL 5.6架构设置

CREATE TABLE Table1
    (`id` int, `channel_id` int, `timestamp` bigint, `value` int)
;

INSERT INTO Table1
    (`id`, `channel_id`, `timestamp`, `value`)
VALUES
    (4515, 7, 1519771680000, 7777),
    (4518, 8, 1519772160000, 6666),
    (4520, 7, 1519772340000, 8888)
;

Query 1 : 查询1

select
      id
    , channel_id
    , timestamp
    , value
    , nxt_value
    , nxt_value - value as diff
from (
    select
          t1.id
        , t1.channel_id
        , t1.timestamp
        , t1.value
        , (select value from table1 as t2 
           where t2.channel_id = t1.channel_id
           and t2.timestamp > t1.timestamp
           order by t2.timestamp
           limit 1) nxt_value
    from table1 as t1
    ) as d

Results : 结果

|   id | channel_id |     timestamp | value | nxt_value |   diff |
|------|------------|---------------|-------|-----------|--------|
| 4515 |          7 | 1519771680000 |  7777 |      8888 |   1111 |
| 4518 |          8 | 1519772160000 |  6666 |    (null) | (null) |
| 4520 |          7 | 1519772340000 |  8888 |    (null) | (null) |

Starting from MySQL 8, you can use window functions , in case of which your query would look like this: 从MySQL 8开始,您可以使用窗口函数 ,如果您的查询如下所示:

SELECT
  id, channel_id, timestamp, value,
  value - LAG(value, 1, 0) OVER (PARTITION BY channel_id ORDER BY timestamp) difference
FROM my_table

thanks for all your support. 感谢您的支持。 I tried a lot and created "my" solution based on a stored procedure. 我尝试了很多,并根据存储过程创建了“我的”解决方案。 It is not as performant as it could be but it delivers the required values. 它没有尽可能高的性能,但它提供了所需的值。

The code is running in a loop with a max size of repetitions in the script execution to avoid an endless step :) 代码在脚本执行中以最大重复次数循环运行,以避免无休止的步骤:)


#Auswahl größer CH10-Wert
set @var_max_ch10vz =
    (
    select max(data.timestamp)
    from volkszaehler.data 
    where data.channel_id=10
    )
;
#Auswahl kleinster offener Wert aus SBFSPOT
set @var_min_sbfspot = 
    (
    select min(data.timestamp_unix*1000)
    from sbfspot_u.data
    where 
        data.timestamp_vzjoin is null 
        and data.timestamp_unix >1522096327
        and data.timestamp_unix*1000 < @var_max_ch10vz
    )
;
#Abgleich gegen VZ von unten
set @var_max_vz =
    (
    select min(data.timestamp)
    from volkszaehler.data 
    where data.channel_id=10 and data.timestamp >= @var_min_sbfspot
    )
;
#Abgleich gegen VZ von oben
set @var_min_vz =
    (
    select max(data.timestamp)
    from volkszaehler.data 
    where data.channel_id=10 and data.timestamp <= @var_min_sbfspot
    )
;
#Auswahl join Zeitstempel
set @vz_join_timestamp =
    (
        select tmp.uxtimestamp 
        from (
            select @var_max_vz as uxtimestamp, abs(@var_min_sbfspot-@var_max_vz) as diff
            UNION
            select @var_min_vz as uxtimestamp, abs(@var_min_sbfspot-@var_min_vz) as diff
            ) tmp
        order by tmp.diff asc
        limit 1
    )
;

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

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