MySQL - Show record pairs in one record
I have the following data in one table:
Time, Type, Kilometers
12:00, 1, 0.1
12:30, 2, 0.2
14:00, 1, 0.4
15:00, 2, 1.0
16:00, 1, 1.2
16:30, 2, 1.5
16:45, 1, 2.0
This data is sorted chronologically using the DateTime field. I would like to show these record 'pairs' as 1 row, like so:
StartTime, Type1Km, Type2Km
12:00, 0.1, 0.2
14:00, 0开发者_JS百科.4, 1.0
16:00, 1.2, 1.5
16:45, 2.0, NULL
There are a couple of caveats: If there is no Type1 to start, then show NULL in the resulting tables' Type1Km field. Similarly, if there is no Type2 end, show NULL in records' Type2Km field.
How could i do this?
Unfortunately, MySQL lacks a FULL OUTER JOIN
, so you'll have to UNION
two sets together.
This will get you the cases where Type1Km
exists, whether or not Type2Km
does.
SELECT
t1.`Time` as StartTime,
t1.`Kilometers` as Type1Km,
t2.`Kilometers` as Type2Km
FROM `times` t1
LEFT JOIN `times` t2 ON t2.`Type` = 2
AND t2.`Time` = (SELECT `Time` FROM `times`
WHERE `Time` > t1.`Time`
ORDER BY `Time` LIMIT 1)
WHERE t1.`Type` = 1
Now we need the cases where Type1Km
does not exist.
SELECT
t2.`Time` as StartTime,
NULL as Type1Km,
t2.`Kilometers` as Type2Km
FROM `times` t2
LEFT JOIN `times` t1 ON t1.`Time` = (SELECT `Time` FROM `times`
WHERE `Time` < t2.`Time`
ORDER BY `Time` DESC LIMIT 1)
WHERE t2.`Type` = 2
AND (t1.`Type` = 2 OR t1.`Type` IS NULL)
UNION
those together, and you have the desired result:
(
SELECT
t1.`Time` as StartTime,
t1.`Kilometers` as Type1Km,
t2.`Kilometers` as Type2Km
FROM `times` t1
LEFT JOIN `times` t2 ON t2.`Type` = 2
AND t2.`Time` = (SELECT `Time` FROM `times`
WHERE `Time` > t1.`Time`
ORDER BY `Time` LIMIT 1)
WHERE t1.`Type` = 1
) UNION ALL (
SELECT
t2.`Time` as StartTime,
NULL as Type1Km,
t2.`Kilometers` as Type2Km
FROM `times` t2
LEFT JOIN `times` t1 ON t1.`Time` = (SELECT `Time` FROM `times`
WHERE `Time` < t2.`Time`
ORDER BY `Time` DESC LIMIT 1)
WHERE t2.`Type` = 2
AND (t1.`Type` = 2 OR t1.`Type` IS NULL)
)
ORDER BY `StartTime`
Update
In my previous query, I forgot to account for having a "type 2" record at the very beginning. Updated to account for that. Here's the results I get:
Data in times
table:
+----------+------+------------+
| Time | Type | Kilometers |
+----------+------+------------+
| 11:00:00 | 2 | 0.1 |
| 12:00:00 | 1 | 0.1 |
| 12:30:00 | 2 | 0.2 |
| 14:00:00 | 1 | 0.4 |
| 14:30:00 | 1 | 0.8 |
| 15:00:00 | 2 | 1.0 |
| 15:30:00 | 2 | 0.2 |
| 16:00:00 | 1 | 1.2 |
| 16:30:00 | 2 | 1.5 |
| 16:45:00 | 1 | 2.0 |
+----------+------+------------+
Results of query:
+-----------+---------+---------+
| StartTime | Type1Km | Type2Km |
+-----------+---------+---------+
| 11:00:00 | NULL | 0.1 |
| 12:00:00 | 0.1 | 0.2 |
| 14:00:00 | 0.4 | NULL |
| 14:30:00 | 0.8 | 1.0 |
| 15:30:00 | NULL | 0.2 |
| 16:00:00 | 1.2 | 1.5 |
| 16:45:00 | 2.0 | NULL |
+-----------+---------+---------+
If you can, change your table structure to have a type1km and a type2km, then either update when adding kms or just sum up when selecting.
This might work
select
max(Time),
substring_index(group_concat(if(type=2,null,Kilometers) order by type),',',1),
substring_index(group_concat(if(type=1,null,Kilometers) order by type desc),',',1)
from your_table
group by date_format(Time, '%H');
i assuming group by the hour, and also worth nothing your example results is not precise
To better explain what this funny query does
group_concat(if(type=2,null,Kilometers) order by type
-- this is ensure the Kilometers must NOT from type=2
group_concat(if(type=1,null,Kilometers) order by type desc
-- this is ensure the Kilometers must NOT from type=1
精彩评论