根据时间戳和布尔值合并 SQL Table 中的两行
Consolidate two rows in a SQL Table based on timestamp and an boolean
出于“历史”原因,我关注table:
CREATE TABLE IF NOT EXISTS `measurement`
(
`measureID` int NOT NULL AUTO_INCREMENT ,
`terraID` int NOT NULL ,
`pinID` int NOT NULL ,
`time` timestamp NOT NULL ,
`value` float NULL ,
`temperature` boolean NOT NULL ,
PRIMARY KEY (`measureID`),
KEY `measure_terraID_FK` (`terraID`),
KEY `measure_pinID_FK` (`pinID`),
CONSTRAINT `measure_terraID_reference` FOREIGN KEY `measure_terraID_FK` (`terraID`) REFERENCES `terrarium` (`terraID`),
CONSTRAINT `measure_pinID_reference` FOREIGN KEY `measure_pinID_FK` (`pinID`) REFERENCES `pins` (`pinID`)
) ENGINE=INNODB COLLATE=utf8mb4_unicode_ci;
| measureID | terraID | pinID | time | value | temperature |
|:----------|---------|-------|---------------------|--------|------------:|
| 1 | 1 | 9 | 2020-04-10 13:00:01 | 34.3 | 0 |
| 2 | 1 | 9 | 2020-04-10 13:00:01 | 26.5 | 1 |
| 3 | 2 | 10 | 2020-04-10 13:00:01 | 35.1 | 0 |
| 4 | 2 | 10 | 2020-04-10 13:00:01 | 32.9 | 1 |
| 5 | 1 | 9 | 2020-04-10 13:05:01 | 34.4 | 0 |
| 6 | 1 | 9 | 2020-04-10 13:05:01 | 26.6 | 1 |
| 7 | 2 | 10 | 2020-04-10 13:05:01 | 35 | 0 |
| 8 | 2 | 10 | 2020-04-10 13:05:01 | 33 | 1 |
[...]
| 38087 | 2 | 10 | 2020-08-31 12:50:02 | 35.9 | 0 |
| 38088 | 2 | 10 | 2020-08-31 12:50:02 | 35 | 1 |
| 38089 | 1 | 11 | 2020-08-31 12:50:02 | 25.187 | 1 |
| 38090 | 2 | 12 | 2020-08-31 12:50:02 | 28.312 | 1 |
| 38091 | 2 | 10 | 2020-08-31 12:55:01 | 35.8 | 0 |
| 38092 | 2 | 10 | 2020-08-31 12:55:01 | 35 | 1 |
| 38093 | 1 | 11 | 2020-08-31 12:55:01 | 25.25 | 1 |
| 38094 | 2 | 12 | 2020-08-31 12:55:01 | 28.375 | 1 |
并希望根据时间和 pinID 将其插入到新的 table 中,以便最终的 table 看起来像这样:
CREATE TABLE IF NOT EXISTS `measurement`
(
`measureID` int NOT NULL AUTO_INCREMENT ,
`terraID` int NOT NULL ,
`pinID` int NOT NULL ,
`time` timestamp NOT NULL ,
`temperature` float NULL ,
`humidity` float NULL ,
PRIMARY KEY (`measureID`),
KEY `measure_terraID_FK` (`terraID`),
KEY `measure_pinID_FK` (`pinID`),
CONSTRAINT `measure_terraID_reference` FOREIGN KEY `measure_terraID_FK` (`terraID`) REFERENCES `terrarium` (`terraID`),
CONSTRAINT `measure_pinID_reference` FOREIGN KEY `measure_pinID_FK` (`pinID`) REFERENCES `pins` (`pinID`)
) ENGINE=INNODB COLLATE=utf8mb4_unicode_ci;
| measureID | terraID | pinID | time | temperature | humidity |
|:----------|---------|-------|---------------------|--------------|---------:|
| 2 | 1 | 9 | 2020-04-10 13:00:01 | 26.5 | 34.3 |
| 4 | 2 | 10 | 2020-04-10 13:00:01 | 32.9 | 35.1 |
| 6 | 1 | 9 | 2020-04-10 13:05:01 | 26.6 | 34.4 |
| 8 | 2 | 10 | 2020-04-10 13:05:01 | 33 | 35 |
[...]
| 38088 | 2 | 10 | 2020-08-31 12:50:02 | 35 | 35.9 |
| 38089 | 1 | 11 | 2020-08-31 12:50:02 | 25.187 | NULL |
| 38090 | 2 | 12 | 2020-08-31 12:50:02 | 28.312 | NULL |
| 38092 | 2 | 10 | 2020-08-31 12:55:01 | 35 | 35.8 |
| 38093 | 1 | 11 | 2020-08-31 12:55:01 | 25.25 | NULL |
| 38094 | 2 | 12 | 2020-08-31 12:55:01 | 28.375 | NULL |
我的SQL版本是mariadb-10.3
我不想丢失任何值,也不关心温度列,因为它是读取值的旧标识符。但是我想修改所有旧条目以转换为新结构。
但是您可以在 IF(temperature=1, value, NULL) 中将其用作温度,在 IF(temperature=0, value, '') 中将其用作湿度或某种程度。
terraID 和 pinID 与其他 table 键控,并非所有传感器都提供温度和湿度。
我没有成功地插入 select 子查询魔法...也许我太笨了,无法解决这个问题。
你能告诉我正确的功能吗?这只是一次触发的手动工作。
如果我没听错,你可以使用条件聚合:
select
min(measureID),
terraID,
pinID,
time,
max(case when temperature = 1 then value end) value,
max(case when temperature = 0 then value end) humidity
from mytable
group by terraID, pinID, time
order by min(measureID)
如果需要,您可以轻松地将其转换为 insert
查询(使用 insert ... select ...
),甚至可以转换为 create table
语句(create table newtable as ...
)。
measureID | terraID | pinID | time | value | humidity
--------: | ------: | ----: | :------------------ | -----: | -------:
2 | 1 | 9 | 2020-04-10 13:00:01 | 26.500 | 34.300
4 | 2 | 10 | 2020-04-10 13:00:01 | 32.900 | 35.100
6 | 1 | 9 | 2020-04-10 13:05:01 | 26.600 | 34.400
8 | 2 | 10 | 2020-04-10 13:05:01 | 33.000 | 35.000
38088 | 2 | 10 | 2020-08-31 12:50:02 | 35.000 | 35.900
38089 | 1 | 11 | 2020-08-31 12:50:02 | 25.187 | null
38090 | 2 | 12 | 2020-08-31 12:50:02 | 28.312 | null
38092 | 2 | 10 | 2020-08-31 12:55:01 | 35.000 | 35.800
38093 | 1 | 11 | 2020-08-31 12:55:01 | 25.250 | null
38094 | 2 | 12 | 2020-08-31 12:55:01 | 28.375 | null
使用LEAD()
window函数:
INSERT INTO new_measurement(measureID, terraID, pinID, time, temperature, humidity)
SELECT measureID, terraID, pinID, time,
CASE temperature WHEN 1 THEN value END,
value
FROM (
SELECT *,
LEAD(terraID) OVER (ORDER BY time DESC) next_terraID,
LEAD(pinID) OVER (ORDER BY time DESC) next_pinID
FROM measurement
) t
WHERE terraID <> next_terraID OR pinID <> next_pinID
出于“历史”原因,我关注table:
CREATE TABLE IF NOT EXISTS `measurement`
(
`measureID` int NOT NULL AUTO_INCREMENT ,
`terraID` int NOT NULL ,
`pinID` int NOT NULL ,
`time` timestamp NOT NULL ,
`value` float NULL ,
`temperature` boolean NOT NULL ,
PRIMARY KEY (`measureID`),
KEY `measure_terraID_FK` (`terraID`),
KEY `measure_pinID_FK` (`pinID`),
CONSTRAINT `measure_terraID_reference` FOREIGN KEY `measure_terraID_FK` (`terraID`) REFERENCES `terrarium` (`terraID`),
CONSTRAINT `measure_pinID_reference` FOREIGN KEY `measure_pinID_FK` (`pinID`) REFERENCES `pins` (`pinID`)
) ENGINE=INNODB COLLATE=utf8mb4_unicode_ci;
| measureID | terraID | pinID | time | value | temperature |
|:----------|---------|-------|---------------------|--------|------------:|
| 1 | 1 | 9 | 2020-04-10 13:00:01 | 34.3 | 0 |
| 2 | 1 | 9 | 2020-04-10 13:00:01 | 26.5 | 1 |
| 3 | 2 | 10 | 2020-04-10 13:00:01 | 35.1 | 0 |
| 4 | 2 | 10 | 2020-04-10 13:00:01 | 32.9 | 1 |
| 5 | 1 | 9 | 2020-04-10 13:05:01 | 34.4 | 0 |
| 6 | 1 | 9 | 2020-04-10 13:05:01 | 26.6 | 1 |
| 7 | 2 | 10 | 2020-04-10 13:05:01 | 35 | 0 |
| 8 | 2 | 10 | 2020-04-10 13:05:01 | 33 | 1 |
[...]
| 38087 | 2 | 10 | 2020-08-31 12:50:02 | 35.9 | 0 |
| 38088 | 2 | 10 | 2020-08-31 12:50:02 | 35 | 1 |
| 38089 | 1 | 11 | 2020-08-31 12:50:02 | 25.187 | 1 |
| 38090 | 2 | 12 | 2020-08-31 12:50:02 | 28.312 | 1 |
| 38091 | 2 | 10 | 2020-08-31 12:55:01 | 35.8 | 0 |
| 38092 | 2 | 10 | 2020-08-31 12:55:01 | 35 | 1 |
| 38093 | 1 | 11 | 2020-08-31 12:55:01 | 25.25 | 1 |
| 38094 | 2 | 12 | 2020-08-31 12:55:01 | 28.375 | 1 |
并希望根据时间和 pinID 将其插入到新的 table 中,以便最终的 table 看起来像这样:
CREATE TABLE IF NOT EXISTS `measurement`
(
`measureID` int NOT NULL AUTO_INCREMENT ,
`terraID` int NOT NULL ,
`pinID` int NOT NULL ,
`time` timestamp NOT NULL ,
`temperature` float NULL ,
`humidity` float NULL ,
PRIMARY KEY (`measureID`),
KEY `measure_terraID_FK` (`terraID`),
KEY `measure_pinID_FK` (`pinID`),
CONSTRAINT `measure_terraID_reference` FOREIGN KEY `measure_terraID_FK` (`terraID`) REFERENCES `terrarium` (`terraID`),
CONSTRAINT `measure_pinID_reference` FOREIGN KEY `measure_pinID_FK` (`pinID`) REFERENCES `pins` (`pinID`)
) ENGINE=INNODB COLLATE=utf8mb4_unicode_ci;
| measureID | terraID | pinID | time | temperature | humidity |
|:----------|---------|-------|---------------------|--------------|---------:|
| 2 | 1 | 9 | 2020-04-10 13:00:01 | 26.5 | 34.3 |
| 4 | 2 | 10 | 2020-04-10 13:00:01 | 32.9 | 35.1 |
| 6 | 1 | 9 | 2020-04-10 13:05:01 | 26.6 | 34.4 |
| 8 | 2 | 10 | 2020-04-10 13:05:01 | 33 | 35 |
[...]
| 38088 | 2 | 10 | 2020-08-31 12:50:02 | 35 | 35.9 |
| 38089 | 1 | 11 | 2020-08-31 12:50:02 | 25.187 | NULL |
| 38090 | 2 | 12 | 2020-08-31 12:50:02 | 28.312 | NULL |
| 38092 | 2 | 10 | 2020-08-31 12:55:01 | 35 | 35.8 |
| 38093 | 1 | 11 | 2020-08-31 12:55:01 | 25.25 | NULL |
| 38094 | 2 | 12 | 2020-08-31 12:55:01 | 28.375 | NULL |
我的SQL版本是mariadb-10.3
我不想丢失任何值,也不关心温度列,因为它是读取值的旧标识符。但是我想修改所有旧条目以转换为新结构。 但是您可以在 IF(temperature=1, value, NULL) 中将其用作温度,在 IF(temperature=0, value, '') 中将其用作湿度或某种程度。
terraID 和 pinID 与其他 table 键控,并非所有传感器都提供温度和湿度。
我没有成功地插入 select 子查询魔法...也许我太笨了,无法解决这个问题。
你能告诉我正确的功能吗?这只是一次触发的手动工作。
如果我没听错,你可以使用条件聚合:
select
min(measureID),
terraID,
pinID,
time,
max(case when temperature = 1 then value end) value,
max(case when temperature = 0 then value end) humidity
from mytable
group by terraID, pinID, time
order by min(measureID)
如果需要,您可以轻松地将其转换为 insert
查询(使用 insert ... select ...
),甚至可以转换为 create table
语句(create table newtable as ...
)。
measureID | terraID | pinID | time | value | humidity --------: | ------: | ----: | :------------------ | -----: | -------: 2 | 1 | 9 | 2020-04-10 13:00:01 | 26.500 | 34.300 4 | 2 | 10 | 2020-04-10 13:00:01 | 32.900 | 35.100 6 | 1 | 9 | 2020-04-10 13:05:01 | 26.600 | 34.400 8 | 2 | 10 | 2020-04-10 13:05:01 | 33.000 | 35.000 38088 | 2 | 10 | 2020-08-31 12:50:02 | 35.000 | 35.900 38089 | 1 | 11 | 2020-08-31 12:50:02 | 25.187 | null 38090 | 2 | 12 | 2020-08-31 12:50:02 | 28.312 | null 38092 | 2 | 10 | 2020-08-31 12:55:01 | 35.000 | 35.800 38093 | 1 | 11 | 2020-08-31 12:55:01 | 25.250 | null 38094 | 2 | 12 | 2020-08-31 12:55:01 | 28.375 | null
使用LEAD()
window函数:
INSERT INTO new_measurement(measureID, terraID, pinID, time, temperature, humidity)
SELECT measureID, terraID, pinID, time,
CASE temperature WHEN 1 THEN value END,
value
FROM (
SELECT *,
LEAD(terraID) OVER (ORDER BY time DESC) next_terraID,
LEAD(pinID) OVER (ORDER BY time DESC) next_pinID
FROM measurement
) t
WHERE terraID <> next_terraID OR pinID <> next_pinID