如何严格顺序查询数据库?

问题描述 投票:0回答:1

我的数据库中有原始数据,其中包含传感器 a、b、c 的测量值,例如:

unique_id;sensor;timestamp
111;A;2024-10-10 08:00:00.000000
222;C;2024-10-10 08:00:00.000000
333;A;2024-10-10 08:00:00.000000
444;A;2024-10-10 08:00:00.000000
555;A;2024-10-10 08:00:00.000000
666;C;2024-10-10 08:00:01.000000
777;C;2024-10-10 08:00:01.000000
888;C;2024-10-10 08:00:01.000000
555;B;2024-10-10 08:00:09.000000
111;A;2024-10-10 08:00:21.000000
444;A;2024-10-10 08:00:24.000000
444;A;2024-10-10 08:00:38.000000
444;B;2024-10-10 08:00:40.000000
666;C;2024-10-10 08:00:42.000000
111;C;2024-10-10 08:00:42.000000
444;B;2024-10-10 08:00:48.000000
111;C;2024-10-10 08:01:02.000000
666;C;2024-10-10 08:01:02.000000
555;C;2024-10-10 08:01:05.000000
444;C;2024-10-10 08:01:09.000000
111;B;2024-10-10 08:01:23.000000
666;C;2024-10-10 08:01:23.000000
222;C;2024-10-10 08:01:23.000000
555;C;2024-10-10 08:01:27.000000
444;C;2024-10-10 08:01:35.000000
555;C;2024-10-10 08:01:38.000000
111;C;2024-10-10 08:01:43.000000
222;C;2024-10-10 08:01:43.000000
555;C;2024-10-10 08:02:00.000000
111;C;2024-10-10 08:02:04.000000
222;C;2024-10-10 08:02:04.000000
666;C;2024-10-10 08:02:04.000000
555;C;2024-10-10 08:02:20.000000
222;C;2024-10-10 08:02:24.000000
111;C;2024-10-10 08:02:24.000000
111;C;2024-10-10 08:02:45.000000
666;C;2024-10-10 08:02:45.000000
666;C;2024-10-10 08:03:05.000000
222;C;2024-10-10 08:03:05.000000
111;C;2024-10-10 08:03:05.000000
111;C;2024-10-10 08:03:26.000000
666;C;2024-10-10 08:03:26.000000
222;C;2024-10-10 08:03:26.000000

我想查询从传感器a传感器c经过传感器b的旅程的每个unique_id的行程时间,第一次出现在a,最后一次出现在c。顺序必须严格a>b>c。我想要一个条件来检查这是否属实。如果 unique_id 在到达 b 之后重新访问传感器 a 或在到达 c 之后重新访问 b,则应从计算中丢弃该 unique_id。

在人工智能的帮助下,我想出了以下解决方案:

WITH sensor_sequences AS (
    SELECT 
        sm.unique_id,
        MIN(CASE WHEN sm.sensor = 'A' THEN sm.timestamp END) AS first_capture_A,
        MIN(CASE WHEN sm.sensor = 'B' THEN sm.timestamp END) AS first_capture_B,
        MAX(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END) AS last_capture_C
    FROM sensor_measurement sm 
    WHERE 
        sm.sensor IN ('A', 'B', 'C')
        AND sm.timestamp BETWEEN '2024-10-10 07:00:00' AND '2024-10-10 12:00:00'
    GROUP BY sm.unique_id
    HAVING 
        MIN(CASE WHEN sm.sensor = 'A' THEN sm.timestamp END) IS NOT NULL 
        AND MIN(CASE WHEN sm.sensor = 'B' THEN sm.timestamp END) IS NOT NULL 
        AND MAX(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END) IS NOT NULL 
        AND MIN(CASE WHEN sm.sensor = 'B' THEN sm.timestamp END) > MIN(CASE WHEN sm.sensor = 'A' THEN sm.timestamp END)  
        AND MAX(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END) > MIN(CASE WHEN sm.sensor = 'B' THEN sm.timestamp END)  
        AND SECONDS_BETWEEN(MAX(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END),MIN(CASE WHEN sm.sensor = 'A' THEN sm.timestamp END)) <= 300  --max time between two timestamps
)
SELECT 
    ss.unique_id,
    ss.first_capture_A AS sensor_A_time,
    ss.first_capture_B AS sensor_B_time,
    ss.last_capture_C AS sensor_C_time,
    SECONDS_BETWEEN(ss.last_capture_C, ss.first_capture_A) AS travel_time_seconds
FROM sensor_sequences ss
ORDER BY ss.first_capture_A;

问题是,它仍然向我显示 unique_id 从传感器 b 回到传感器 a 的行程时间,但我无法解决这个问题。如何调整查询以仅获得严格的顺序 a>b>c? unique_id 111 应该被丢弃,但它被使用了。

sql datetime exasol
1个回答
0
投票

如果添加此行,您可以排除示例中的问题

WITH sensor_sequences AS (
    SELECT 
        sm.unique_id,
        MIN(CASE WHEN sm.sensor = 'A' THEN sm.timestamp END) AS first_capture_A,
        MIN(CASE WHEN sm.sensor = 'B' THEN sm.timestamp END) AS first_capture_B,
        MAX(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END) AS last_capture_C
    FROM sensor_measurement sm 
    WHERE 
        sm.sensor IN ('A', 'B', 'C')
        AND sm.timestamp BETWEEN '2024-10-10 07:00:00' AND '2024-10-10 12:00:00'
    GROUP BY sm.unique_id
    HAVING 
        MIN(CASE WHEN sm.sensor = 'A' THEN sm.timestamp END) IS NOT NULL 
        AND MIN(CASE WHEN sm.sensor = 'B' THEN sm.timestamp END) IS NOT NULL 
        AND MAX(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END) IS NOT NULL 
        AND MIN(CASE WHEN sm.sensor = 'B' THEN sm.timestamp END) > MIN(CASE WHEN sm.sensor = 'A' THEN sm.timestamp END)  
        AND MAX(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END) > MIN(CASE WHEN sm.sensor = 'B' THEN sm.timestamp END)  
        AND MIN(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END) > MIN(CASE WHEN sm.sensor = 'B' THEN sm.timestamp END)    

        --Exclude ids that have any Cs before Bs
        AND MIN(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END) > MIN(CASE WHEN sm.sensor = 'B' THEN sm.timestamp END)            --AND SECONDS_BETWEEN(MAX(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END),MIN(CASE WHEN sm.sensor = 'A' THEN sm.timestamp END)) <= 300  --max time between two timestamps
  
        AND DATEDIFF(second,
                     MAX(CASE WHEN sm.sensor = 'C' THEN sm.timestamp END),
                     MIN(CASE WHEN sm.sensor = 'A' THEN sm.timestamp END)
                     ) <= 300  --max time between two timestamps
)
SELECT 
    ss.unique_id,
    ss.first_capture_A AS sensor_A_time,
    ss.first_capture_B AS sensor_B_time,
    ss.last_capture_C AS sensor_C_time,
    --SECONDS_BETWEEN(ss.last_capture_C, ss.first_capture_A) AS travel_time_seconds
    DATEDIFF(second,ss.last_capture_C, ss.first_capture_A) AS travel_time_seconds
FROM sensor_sequences ss
ORDER BY ss.first_capture_A;
© www.soinside.com 2019 - 2024. All rights reserved.