2011-08-11 27 views
8

tôi có các dữ liệu sau trong một bảng:MySQL - Hiện cặp kỷ lục trong một bản ghi

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 

Những thông tin này được sắp xếp thứ tự thời gian sử dụng lĩnh vực DateTime. Tôi muốn hiển thị 'cặp' những kỷ lục như 1 hàng, như vậy:

StartTime, Type1Km, Type2Km 
12:00, 0.1, 0.2 
14:00, 0.4, 1.0 
16:00, 1.2, 1.5 
16:45, 2.0, NULL 

Có một số khó khăn: Nếu không có Type1 để bắt đầu, sau đó hiển thị NULL trong lĩnh vực Type1Km các bảng kết quả. Tương tự, nếu không có kết thúc Type2, hiển thị NULL trong trường 'Type2Km'.

Tôi làm cách nào để thực hiện việc này?

+0

Phần khó khăn là bạn đang tham gia một thời gian với loại 1 với thời gian tiếp theo của loại 2. Nếu có 2 loại 1 "trong một hàng", thì Type2Km phải là null, phải không? – MPelletier

+0

@MPelletier - chính xác (điều này khó xảy ra, nhưng sẽ có lợi nếu giải pháp đưa vào tài khoản này) – Simon

+0

Tôi sẽ dễ dàng giải quyết hơn nếu bảng này có cột tăng tự động để liên kết X với X + 1 cho kiểm tra vi phân ... Có một, và chỉ không trình bày ở trên? – DRapp

Trả lời

4

Thật không may, MySQL thiếu FULL OUTER JOIN, vì vậy bạn sẽ phải UNION hai bộ cùng nhau.

Điều này sẽ giúp bạn có được các trường hợp có số Type1Km, có hoặc không Type2Km.

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 

Bây giờ chúng tôi cần các trường hợp trong đó Type1Km không tồn tại.

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 những với nhau, và bạn có kết quả mong muốn:

(
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` 

Cập nhật

Trong truy vấn trước đây của tôi, tôi quên để giải thích cho việc có một "loại 2 "ghi lại ngay từ đầu. Đã cập nhật tài khoản cho điều đó. Dưới đây là kết quả tôi nhận được:

dữ liệu trong times bảng:

+----------+------+------------+ 
| 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 | 
+----------+------+------------+ 

Kết quả truy vấn:

+-----------+---------+---------+ 
| 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 | 
+-----------+---------+---------+ 
+0

+1 cho UNION. Tôi cũng nghĩ vậy :) – MPelletier

0

Nếu bạn có thể, thay đổi cấu trúc bảng của bạn để có một type1km và type2km, sau đó hoặc cập nhật khi thêm km hoặc tổng hợp khi chọn.

0

này có thể làm việc

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'); 

tôi giả sử nhóm theo giờ, và cũng có giá trị gì kết quả ví dụ của bạn là không chính xác

Để giải thích rõ hơn những gì truy vấn vui này không

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 
Các vấn đề liên quan