Skip to content

Latest commit

 

History

History
186 lines (170 loc) · 9.17 KB

File metadata and controls

186 lines (170 loc) · 9.17 KB
DROP TABLE IF EXISTS car; -- 如果表已存在则删除重来

CREATE TABLE car (
    device_id VARCHAR(50) PRIMARY KEY,
    trip_ids INTEGER[],                 -- 行程 ID 数组
    trips_distance FLOAT[],             -- 每一个行程对应的里程数数组
    total_distance FLOAT DEFAULT 0,      -- 该车总里程数
    trips_total INTEGER DEFAULT 0,       -- 总行程数
    
    -- 每个时间段的行程数统计 (Count)
    trips_total_0_2 INTEGER DEFAULT 0,
    trips_total_2_4 INTEGER DEFAULT 0,
    trips_total_4_6 INTEGER DEFAULT 0,
    trips_total_6_8 INTEGER DEFAULT 0,
    trips_total_8_10 INTEGER DEFAULT 0,
    trips_total_10_12 INTEGER DEFAULT 0,
    trips_total_12_14 INTEGER DEFAULT 0,
    trips_total_14_16 INTEGER DEFAULT 0,
    trips_total_16_18 INTEGER DEFAULT 0,
    trips_total_18_20 INTEGER DEFAULT 0,
    trips_total_20_22 INTEGER DEFAULT 0,
    trips_total_22_24 INTEGER DEFAULT 0,

    -- 每个时间段的里程数统计 (Sum)
    total_distance_0_2 FLOAT DEFAULT 0,
    total_distance_2_4 FLOAT DEFAULT 0,
    total_distance_4_6 FLOAT DEFAULT 0,
    total_distance_6_8 FLOAT DEFAULT 0,
    total_distance_8_10 FLOAT DEFAULT 0,
    total_distance_10_12 FLOAT DEFAULT 0,
    total_distance_12_14 FLOAT DEFAULT 0,
    total_distance_14_16 FLOAT DEFAULT 0,
    total_distance_16_18 FLOAT DEFAULT 0,
    total_distance_18_20 FLOAT DEFAULT 0,
    total_distance_20_22 FLOAT DEFAULT 0,
    total_distance_22_24 FLOAT DEFAULT 0
);
INSERT INTO car (
    device_id, 
    trip_ids, 
    trips_distance,
    total_distance,
    trips_total,
    -- 行程数统计字段
    trips_total_0_2, trips_total_2_4, trips_total_4_6, trips_total_6_8, 
    trips_total_8_10, trips_total_10_12, trips_total_12_14, trips_total_14_16, 
    trips_total_16_18, trips_total_18_20, trips_total_20_22, trips_total_22_24,
    -- 里程数统计字段
    total_distance_0_2, total_distance_2_4, total_distance_4_6, total_distance_6_8, 
    total_distance_8_10, total_distance_10_12, total_distance_12_14, total_distance_14_16, 
    total_distance_16_18, total_distance_18_20, total_distance_20_22, total_distance_22_24
)
SELECT 
    devid,
    -- 1. 聚合数组
    array_agg(trip_id ORDER BY start_time),
    array_agg(distance_km ORDER BY start_time),
    -- 2. 总体统计
    SUM(distance_km),
    COUNT(trip_id),
    
    -- 3. 分时段行程数 (Count)
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 0  AND EXTRACT(HOUR FROM start_time::timestamp) < 2),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 2  AND EXTRACT(HOUR FROM start_time::timestamp) < 4),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 4  AND EXTRACT(HOUR FROM start_time::timestamp) < 6),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 6  AND EXTRACT(HOUR FROM start_time::timestamp) < 8),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 8  AND EXTRACT(HOUR FROM start_time::timestamp) < 10),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 10 AND EXTRACT(HOUR FROM start_time::timestamp) < 12),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 12 AND EXTRACT(HOUR FROM start_time::timestamp) < 14),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 14 AND EXTRACT(HOUR FROM start_time::timestamp) < 16),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 16 AND EXTRACT(HOUR FROM start_time::timestamp) < 18),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 18 AND EXTRACT(HOUR FROM start_time::timestamp) < 20),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 20 AND EXTRACT(HOUR FROM start_time::timestamp) < 22),
    COUNT(trip_id) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 22 AND EXTRACT(HOUR FROM start_time::timestamp) < 24),

    -- 4. 分时段里程数 (Sum)
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 0  AND EXTRACT(HOUR FROM start_time::timestamp) < 2), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 2  AND EXTRACT(HOUR FROM start_time::timestamp) < 4), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 4  AND EXTRACT(HOUR FROM start_time::timestamp) < 6), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 6  AND EXTRACT(HOUR FROM start_time::timestamp) < 8), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 8  AND EXTRACT(HOUR FROM start_time::timestamp) < 10), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 10 AND EXTRACT(HOUR FROM start_time::timestamp) < 12), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 12 AND EXTRACT(HOUR FROM start_time::timestamp) < 14), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 14 AND EXTRACT(HOUR FROM start_time::timestamp) < 16), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 16 AND EXTRACT(HOUR FROM start_time::timestamp) < 18), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 18 AND EXTRACT(HOUR FROM start_time::timestamp) < 20), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 20 AND EXTRACT(HOUR FROM start_time::timestamp) < 22), 0),
    COALESCE(SUM(distance_km) FILTER (WHERE EXTRACT(HOUR FROM start_time::timestamp) >= 22 AND EXTRACT(HOUR FROM start_time::timestamp) < 24), 0)
FROM trip_data
GROUP BY devid;
-- 如果表已存在,建议删除重来以确保字段顺序一致
DROP TABLE IF EXISTS trip_data CASCADE;

CREATE TABLE trip_data (
    -- 1. 原始 CSV 对应的列 (必须与 CSV 列顺序或 \copy 指定顺序一致)
    devid VARCHAR(50),                 -- 车辆 ID
    lon FLOAT[],                       -- 经度数组
    lat FLOAT[],                       -- 纬度数组
    tms BIGINT[],                      -- Unix 时间戳数组
    roads INT[],                       -- 道路 ID 数组
    time FLOAT[],                    -- 原始行程时间数组 (CSV 中的 time 列)
    frac FLOAT[],                      -- 行程分数/进度数组
    route INT[],                       -- 路径 ID 数组
    route_heading INT[],               -- 航向角数组
    log_date DATE NOT NULL,            -- 日期 (分区键)

    -- 2. 数据库生成的自增 ID 和 衍生计算列
    trip_id SERIAL,                    -- 行程自增 ID
    distance_km FLOAT,                 -- 总里程 (待计算)
    duration INTERVAL,                 -- 总耗时 (待计算)
    start_time TIMESTAMP,              -- 开始时间 (待计算)
    end_time TIMESTAMP,                -- 结束时间 (待计算)
    speed_array FLOAT[],               -- 瞬时速度数组 (待计算)

    PRIMARY KEY (trip_id, log_date)
) PARTITION BY RANGE (log_date);

-- 为 2015年1月3日 创建分区子表
CREATE TABLE trip_data_20150103 PARTITION OF trip_data
    FOR VALUES FROM ('2015-01-03') TO ('2015-01-04');

-- 如果还有其他日期,以此类推
CREATE TABLE trip_data_20150104 PARTITION OF trip_data
    FOR VALUES FROM ('2015-01-04') TO ('2015-01-05');

-- psql执行
\copy trip_data (devid, lon, lat, tms, roads, time, frac, route, route_heading, log_date) FROM 'D:/Desktop/TheaTang/code/Data_Platform/trip_data_correct.csv' WITH (FORMAT csv, HEADER true, QUOTE '"', DELIMITER ',');


WITH trip_calculations AS (
    SELECT 
        trip_id,
        log_date,
        -- 计算总里程 (km)
        ST_Length(
            ST_SetSRID(
                ST_MakeLine(
                    ARRAY(
                        SELECT ST_MakePoint(lon[i], lat[i])
                        FROM generate_series(1, array_upper(lon, 1)) AS i
                    )
                ), 4326
            )::geography
        ) / 1000.0 AS calc_dist,
        -- 计算时间
        to_timestamp(tms[1]) AS calc_start,
        to_timestamp(tms[array_upper(tms, 1)]) AS calc_end,
        to_timestamp(tms[array_upper(tms, 1)]) - to_timestamp(tms[1]) AS calc_duration,
        -- 计算速度数组
        (
            SELECT array_agg(s.v ORDER BY s.idx) 
            FROM (
                SELECT 
                    idx,
                    CASE 
                        WHEN (tms[idx] - tms[idx-1]) > 0 THEN 
                            ROUND((ST_Distance(
                                ST_MakePoint(lon[idx], lat[idx])::geography, 
                                ST_MakePoint(lon[idx-1], lat[idx-1])::geography
                            ) / (tms[idx] - tms[idx-1]) * 3.6)::numeric, 2)
                        ELSE 0 
                    END AS v
                FROM generate_series(2, array_upper(lon, 1)) AS idx
            ) s
        ) AS calc_speeds
    FROM trip_data
    WHERE array_upper(lon, 1) > 1
)
UPDATE trip_data t
SET 
    distance_km = c.calc_dist,
    duration = c.calc_duration,
    start_time = c.calc_start,
    end_time = c.calc_end,
    speed_array = c.calc_speeds
FROM trip_calculations c
WHERE t.trip_id = c.trip_id AND t.log_date = c.log_date;