我在试着计算人们在一个地方花了多少时间.为此,我们有node_address代表一个人,areaName和时间,当人被看到.

Original Data

date areaName node_address/person
8:15 area1 1
8:20 area1 1
8:25 area1 1
8:30 area1 1
8:45 area1 1
9:00 area1 1
8:15 area2 2
8:20 area2 2
9:00 area2 1
9:05 area2 2
9:10 area2 2

Expected Data

areaName | time
area1    | 25 min
area2    | 15 min

这些时间的理由是以下条件:

人1在area1内从8:15到8:30—15分钟(因为被看到的间隔小于10分钟),也被看到在8:45—5分钟(它被认为是5分钟,因为它只有一次,没有其他记录小于10分钟),9:00—5分钟.

同样的人2,是在area2从8:15到8:20—5分钟,并被看到从9:00到9:10—10分钟.

我能够开发一个查询,以获得上一个时间和下一个时间的差异,我也做了一个验证,以判断它是否比较同一个人:

SELECT
        date,
        node_address,
        areaName,
        CASE
            WHEN node_address = LAG(node_address) OVER (ORDER BY areaName, node_address, date)
            THEN DATETIME_DIFF(date, LAG(date) OVER (ORDER BY areaName, node_address, date), MINUTE)
            ELSE NULL
        END AS PrevDiff,
        CASE
            WHEN node_address = LEAD(node_address) OVER (ORDER BY areaName, node_address, date)
            THEN DATETIME_DIFF(LEAD(date) OVER (ORDER BY areaName, node_address, date), date, MINUTE)
            ELSE NULL
        END AS NextDiff
    FROM . . .

(但我无法找到这样的计算方法)

推荐答案

创建一些数据来处理.

-- Simulate the input data into a table called NodeAddresses.
DROP TABLE IF EXISTS NodeAddresses;
CREATE TABLE NodeAddresses(area_date DATETIME NOT NULL
                                , area_name CHAR(5) NOT NULL
                                , node_address BIGINT NOT NULL
                                );
                                
INSERT INTO NodeAddresses(area_date
                        , area_name
                        , node_address
                        )
VALUES ('2024-01-01 08:15:00', 'area1', 1)
    , ('2024-01-01 08:20:00', 'area1', 1)
    , ('2024-01-01 08:25:00', 'area1', 1)
    , ('2024-01-01 08:30:00', 'area1', 1)
    , ('2024-01-01 08:45:00', 'area1', 1)
    , ('2024-01-01 09:00:00', 'area1', 1)
    , ('2024-01-01 08:15:00', 'area2', 2)
    , ('2024-01-01 08:20:00', 'area2', 2)
    , ('2024-01-01 09:00:00', 'area2', 1)
    , ('2024-01-01 09:05:00', 'area2', 2)
    , ('2024-01-01 09:10:00', 'area2', 2);

查找每个 node 地址和区域的上一个日期和下一个日期.使用该值计算该 node 地址在该区域中的时间差.根据您的10分钟间隔条件调整时差.确定每个区域的时间总和.

SELECT subq3.area_name
    , SUM(subq3.minutes_spent_in_area) AS total_minutes_in_area
FROM(
    SELECT CASE 
            WHEN (minutes_since_previous >= 10 OR minutes_since_previous IS NULL) AND (minutes_till_next >= 10 OR minutes_till_next IS NULL)
                THEN 5
            WHEN minutes_since_previous >= 10
                THEN 0
            ELSE minutes_since_previous
        END AS minutes_spent_in_area
        , area_name
    FROM(
        SELECT TIMESTAMPDIFF(MINUTE, previous_area_date, area_date) AS minutes_since_previous
            , TIMESTAMPDIFF(MINUTE, area_date, next_area_date) AS minutes_till_next
            , area_name
        FROM(
            SELECT area_date
                , LAG(area_date) OVER(PARTITION BY node_address, area_name ORDER BY area_date ASC) AS previous_area_date
                , LEAD(area_date) OVER(PARTITION BY node_address, area_name ORDER BY area_date ASC) AS next_area_date
                , area_name
                , node_address
            FROM NodeAddresses
            ) subq
        ) subq2
    ) subq3
GROUP BY subq3.area_name;
area_name total_minutes_in_area
area1 25
area2 15

自己试试:db<>fiddle

Sql相关问答推荐

如何在SQL查询中只比较日期时间的年份和月份(而忽略日期比较)?

用于平均多个数据并与一个数据点进行比较以判断偏移量的SQL查询

用相同值更新行

SQL查询视图与连接?

解析SQL Server中的嵌套JSON

如何查询jsonb列是一个对象数组?

防止ActiveRecord迁移在db/structure.sql中进行巨大更改

根据是否出现过零来筛选数据(跨多行)

按行值出现的顺序对行值进行分组

仅当 SQL Server 中的表为开时,才在存储过程中使用更改跟踪

如何为 ActiveRecord 联接应用附加条件

SQL:无重复项的两个聚合函数

Postgres数据库维护:基于GROUP BY删除旧记录

使用ALTER TABLE无法删除列

当该日期的至少两条记录具有相同的持续时间或至少一条记录的持续时间为 0 时,如何标记该日期的所有记录

SQL - 只需要 GROUP BY SELECT 的一列

为数组中的每个元素从表中收集最大整数

从每行中排除最大元素

postgreSQL 中的循环表

从多个连接返回 1 行到同一个表 - SQL Server