英文:
Oracle SQL Query - Between Two Timestamp
问题
对于一份报告,我需要根据他们的活动,跟踪人员在给定时间范围内从一个地方到另一个地方的移动。
从上表中,假设我们需要跟踪人们从上午8点到晚上8点(08:00至20:00)的移动,结果如下:
使用WHERE子句中的BETWEEN可以获取在给定范围内的活动。但我无法获取每个人的第一个“出发地”,因为它超出了时间范围。我尝试过使用GROUP BY和窗口函数,但仍然无法获得所需的结果。有人可以帮忙吗?
姓名 | 出发地 | 目的地 |
---|---|---|
Peter | ????? | 餐厅 |
Peter | 餐厅 | 办公室 |
Peter | 办公室 | 高尔夫 |
John | ????? | 健身房 |
John | 健身房 | 剧院 |
John | 剧院 | 足球场 |
英文:
For a report, i need to track movement of persons from one place to another within a given time range, based on their activities
Activities
Name | TimeStamp | Activity |
---|---|---|
Peter | 10-JAN-23 05:23:06 | Gym |
Peter | 10-JAN-23 07:01:45 | Home |
Peter | 10-JAN-23 08:09:26 | Restaurant |
Peter | 10-JAN-23 09:19:32 | Office |
Peter | 10-JAN-23 16:43:02 | Golf |
John | 10-JAN-23 07:30:26 | Home |
John | 10-JAN-23 08:30:43 | Gym |
John | 10-JAN-23 10:02:06 | Theater |
John | 10-JAN-23 12:00:32 | Soccer |
John | 10-JAN-23 20:23:02 | Bar |
From the above table, let's say we need to track movement of people from 8AM to 8PM (08:00 to 20:00) the result would be as below.
Name | From | To |
---|---|---|
Peter | Home | Restaurant |
Peter | Restaurant | Office |
Peter | Office | Golf |
John | Home | Gym |
John | Gym | Theater |
John | Theater | Soccer |
Using BETWEEN in WHERE CLAUSE the activity between the given range can be fetched. But I am unable to get the first 'FROM' place of each person as it falls outside the time range. I have tried with group by and window functions, but still unable to get the desired result. Can someone please help on this ?
Name | From | To |
---|---|---|
Peter | ????? | Restaurant |
Peter | Restaurant | Office |
Peter | Office | Golf |
John | ????? | Gym |
John | Gym | Theater |
John | Theater | Soccer |
答案1
得分: 2
使用内部查询中的LAG
分析函数,然后在外部查询中按时间范围进行筛选(如果您反过来做,那么您将在使用LAG
查找之前过滤掉范围开始之前的值):
SELECT name,
prev_activity AS "FROM",
activity AS "TO"
FROM (
SELECT a.*,
LAG(activity) OVER (PARTITION BY name ORDER BY timestamp) AS prev_activity
FROM activities a
)
WHERE timestamp BETWEEN TIMESTAMP '2023-01-10 08:00:00'
AND TIMESTAMP '2023-01-10 20:00:00';
对于示例数据:
CREATE TABLE activities ( Name, TimeStamp, Activity ) AS
SELECT 'Peter', TIMESTAMP '2023-01-10 05:23:06', 'Gym' FROM DUAL UNION ALL
SELECT 'Peter', TIMESTAMP '2023-01-10 07:01:45', 'Home' FROM DUAL UNION ALL
SELECT 'Peter', TIMESTAMP '2023-01-10 08:09:26', 'Restaurant' FROM DUAL UNION ALL
SELECT 'Peter', TIMESTAMP '2023-01-10 09:19:32', 'Office' FROM DUAL UNION ALL
SELECT 'Peter', TIMESTAMP '2023-01-10 16:43:02', 'Golf' FROM DUAL UNION ALL
SELECT 'John', TIMESTAMP '2023-01-10 07:30:26', 'Home' FROM DUAL UNION ALL
SELECT 'John', TIMESTAMP '2023-01-10 08:30:43', 'Gym' FROM DUAL UNION ALL
SELECT 'John', TIMESTAMP '2023-01-10 10:02:06', 'Theater' FROM DUAL UNION ALL
SELECT 'John', TIMESTAMP '2023-01-10 12:00:32', 'Soccer' FROM DUAL UNION ALL
SELECT 'John', TIMESTAMP '2023-01-10 20:23:02', 'Bar' FROM DUAL;
输出结果:
NAME | FROM | TO |
---|---|---|
John | Home | Gym |
John | Gym | Theater |
John | Theater | Soccer |
Peter | Home | Restaurant |
Peter | Restaurant | Office |
Peter | Office | Golf |
英文:
Use the LAG
analytic function in an inner-query and then filter on the time range in an outer query (if you do it the other way round then you will filter out the value before the start of the range before you can find it using LAG
):
SELECT name,
prev_activity AS "FROM",
activity AS "TO"
FROM (
SELECT a.*,
LAG(activity) OVER (PARTITION BY name ORDER BY timestamp) AS prev_activity
FROM activites a
)
WHERE timestamp BETWEEN TIMESTAMP '2023-01-10 08:00:00'
AND TIMESTAMP '2023-01-10 20:00:00';
Which, for the sample data:
CREATE TABLE activities ( Name, TimeStamp, Activity ) AS
SELECT 'Peter', TIMESTAMP '2023-01-10 05:23:06', 'Gym' FROM DUAL UNION ALL
SELECT 'Peter', TIMESTAMP '2023-01-10 07:01:45', 'Home' FROM DUAL UNION ALL
SELECT 'Peter', TIMESTAMP '2023-01-10 08:09:26', 'Restaurant' FROM DUAL UNION ALL
SELECT 'Peter', TIMESTAMP '2023-01-10 09:19:32', 'Office' FROM DUAL UNION ALL
SELECT 'Peter', TIMESTAMP '2023-01-10 16:43:02', 'Golf' FROM DUAL UNION ALL
SELECT 'John', TIMESTAMP '2023-01-10 07:30:26', 'Home' FROM DUAL UNION ALL
SELECT 'John', TIMESTAMP '2023-01-10 08:30:43', 'Gym' FROM DUAL UNION ALL
SELECT 'John', TIMESTAMP '2023-01-10 10:02:06', 'Theater' FROM DUAL UNION ALL
SELECT 'John', TIMESTAMP '2023-01-10 12:00:32', 'Soccer' FROM DUAL UNION ALL
SELECT 'John', TIMESTAMP '2023-01-10 20:23:02', 'Bar' FROM DUAL;
Outputs:
NAME | FROM | TO |
---|---|---|
John | Home | Gym |
John | Gym | Theater |
John | Theater | Soccer |
Peter | Home | Restaurant |
Peter | Restaurant | Office |
Peter | Office | Golf |
答案2
得分: 1
使用窗口函数 LAG(activity)
或 LEAD(activity) OVER (PARTITION BY name ORDER BY timestamp)
来显示前一个(或下一个)位置。这就是你的FROM(或TO,无论你喜欢哪个)。完成。
英文:
Use the windowing LAG(activity)
or LEAD(activity) OVER (PARTITION BY name ORDER BY timestamp)
to show the previous (or next) location. That's your FROM (or TO, whichever you prefer). Done.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论