mysql:一列中的值之间的差异
mysql: difference between values in one column
这个板在过去帮助了我几次。
我的挑战:我想获得一列中的值之间的差异。
table 看起来像这样:
id | channel_id | timestamp | value
4515| 7 |1519771680000 | 7777
4518| 8 |1519772160000 | 6666
4520| 7 |1519772340000 | 8888
- id:来自数据源的内部 ID。在某些情况下,它是有序的,在其他情况下则不是。我们不能强行执行此命令。
- channel_id: 不同的数据源。
- 时间戳:unix 时间戳。
- value:测量值。
我想做的事情:
过滤器(例如 channel_id = 7)。
计算一个时间戳与下一个时间戳之间的差异。在这个例子中:8888-7777
我在另一个数据库上找到了解决方案,但我无法将其传输到 mysql,因为 windows 功能非常有限。你们中有人知道如何获得可用于 select 语句的解决方案吗?
感谢 KR
霍尔格
您可以通过将 table 连接到自身来比较(即减去)两行:
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
您可以为此使用 "correlated subquery",如下所示 (also see this demo)。当 MySQL 实现 window 函数时,例如 LEAD()
你可以使用它们。
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)
;
查询 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
| 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) |
从 MySQL 8 开始,您可以使用 window functions,在这种情况下,您的查询将如下所示:
SELECT
id, channel_id, timestamp, value,
value - LAG(value, 1, 0) OVER (PARTITION BY channel_id ORDER BY timestamp) difference
FROM my_table
感谢大家的支持。我尝试了很多并基于存储过程创建了 "my" 解决方案。它的性能不如预期,但它提供了所需的值。
代码是 运行 循环,在脚本执行中有最大重复次数以避免无休止的步骤:)
#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
)
;
这个板在过去帮助了我几次。
我的挑战:我想获得一列中的值之间的差异。
table 看起来像这样:
id | channel_id | timestamp | value
4515| 7 |1519771680000 | 7777
4518| 8 |1519772160000 | 6666
4520| 7 |1519772340000 | 8888
- id:来自数据源的内部 ID。在某些情况下,它是有序的,在其他情况下则不是。我们不能强行执行此命令。
- channel_id: 不同的数据源。
- 时间戳:unix 时间戳。
- value:测量值。
我想做的事情:
过滤器(例如 channel_id = 7)。 计算一个时间戳与下一个时间戳之间的差异。在这个例子中:8888-7777
我在另一个数据库上找到了解决方案,但我无法将其传输到 mysql,因为 windows 功能非常有限。你们中有人知道如何获得可用于 select 语句的解决方案吗?
感谢 KR 霍尔格
您可以通过将 table 连接到自身来比较(即减去)两行:
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
您可以为此使用 "correlated subquery",如下所示 (also see this demo)。当 MySQL 实现 window 函数时,例如 LEAD()
你可以使用它们。
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)
;
查询 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
| 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) |
从 MySQL 8 开始,您可以使用 window functions,在这种情况下,您的查询将如下所示:
SELECT
id, channel_id, timestamp, value,
value - LAG(value, 1, 0) OVER (PARTITION BY channel_id ORDER BY timestamp) difference
FROM my_table
感谢大家的支持。我尝试了很多并基于存储过程创建了 "my" 解决方案。它的性能不如预期,但它提供了所需的值。
代码是 运行 循环,在脚本执行中有最大重复次数以避免无休止的步骤:)
#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
)
;