Oracle SQL中的FIRST和LAST值

问题描述

我在查询某些数据时遇到问题。我尝试从中提取数据的表是一个LOG表,我想在其中查看彼此相邻的值的变化(下面的示例)

表格:


+-----------+----+-------------+----------+------------+
| UNIQUE_ID | ID |    NAME     |   CITY   |    DATE    |
+-----------+----+-------------+----------+------------+
| xa220     |  1 | John Smith  | Berlin   | 2020.05.01 |
| xa195     |  1 | John Smith  | Berlin   | 2020.03.01 |
| xa111     |  1 | John Smith  | München  | 2020.01.01 |
| xa106     |  2 | James brown | Atlanta  | 2018.04.04 |
| xa100     |  2 | James brown | Boston   | 2017.12.10 |
| xa76      |  3 | Emily Wolf  | Shanghai | 2016.11.03 |
| xa20      |  3 | Emily Wolf  | Shanghai | 2016.07.03 |
| xa15      |  3 | Emily Wolf  | Tokyo    | 2014.02.22 |
| xa12      |  3 | Emily Wolf  | null     | 2014.02.22 |
+-----------+----+-------------+----------+------------+

所需结果:

+----+-------------+----------+---------------+
| ID |    NAME     |   CITY   | PREVIoUS_CITY |
+----+-------------+----------+---------------+
|  1 | John Smith  | Berlin   | München       |
|  2 | James brown | Atlanta  | Boston        |
|  3 | Emily Wolf  | Shanghai | Tokyo         |
|  3 | Emily Wolf  | Tokyo    | null          |
+----+-------------+----------+---------------+

我一直在尝试使用FirsT和LAST值,但是无法获得理想的结果。

select distinct id,name,city,first_value(city) over (partition by id order by city) as prevIoUs_city
from test

感谢您的帮助! 谢谢!

解决方法

使用LAG函数获取上一个日期的城市,并仅显示当前城市和滞后结果不同的行:

WITH cte AS (
    SELECT t.*,LAG(CITY,1,CITY) OVER (PARTITION BY ID ORDER BY "DATE") LAG_CITY
    FROM yourTable t
)

SELECT ID,NAME,CITY,LAG_CITY AS PREVIOUS_CITY
FROM cte
WHERE
    CITY <> LAG_CITY OR
    CITY IS NULL AND LAG_CITY IS NOT NULL OR
    CITY IS NOT NULL AND LAG_CITY IS NULL
ORDER BY
    ID,"DATE" DESC;

screen capture from demo link below

Demo

对于LAG的使用方式和检查其值的某些评论是必要的。我们在这里使用LAG的三个参数版本。第二个参数表示要回顾的记录数,在这种情况下为1(默认值)。第三个参数表示如果每个ID分区的给定记录为 first ,则使用默认值。在这种情况下,我们使用默认值作为相同的CITY值。这意味着第一条记录将永远不会出现在结果集中。

对于上面的WHERE子句,匹配记录是城市和滞后城市不同的记录,其中两个是NULL且其他不是NULL。这是将NULL城市和某些NULL城市价值视为不同的逻辑。