繁体   English   中英

对于每个唯一的记录 ID,返回类型 Y 的最新记录当且仅当存在类型 X 的更新记录

[英]For each unique record ID, return the most recent record of type Y iff there is a more recent record of type X

对于每个唯一的记录 ID,返回类型 Y 的最新记录当且仅当存在类型 X 的更新记录

为了使解释更容易,我将按 EventDate 降序排列记录,并只查看特定的记录 ID。 (最近在顶部。)

情况1

ID 活动日期 类型
1个 一些日期 其他(多条记录)
1个 7月29日 X
1个 2月23日
1个 1月3日
1个 一些日期 其他(多条记录)

类型 Y 的返回记录从 2 月 23 日开始(2 月 23 日与类型 X 的记录日期 1 月 1 日比较接近)

案例二

ID 活动日期 类型
2个 一些日期 其他(多条记录)
2个 11 月 2 日 X
2个 10 月 31 日
2个 一些日期 其他的东西
2个 7月2日 X
2个 2月23日
2个 1月5日
2个 一些日期 其他的东西

返回类型 Y 的 2 月 23 日和类型 Y 的 10 月 31 日的记录。这些是分别在日期方面最接近类型 X 记录的记录。 (2 月 23 日的 y 型最接近 7 月 2 日的 X 型,10 月 31 日的 Y 型最接近 11 月 2 日的 X 型)

案例三

ID 活动日期 类型
3个 一些日期 其他(多条记录)
3个 7月2日 X
3个 2月23日
3个 一些日期 其他的东西
3个 1月5日 X
3个 一些日期 其他的东西

返回 Feb 23 类型 Y 记录

案例四

ID 活动日期 类型
4个 一些日期 其他(多条记录)
4个 10 月 15 日
4个 7月2日 X
5个 2月23日 X
5个 一些日期 其他的东西
5个 1月5日
5个 1 月 1 日
5个 一些日期 其他的东西

仅返回类型 Y 记录的 1 月 5 日。 就发生在类型 X 之前的日期而言,它最接近类型 X 的记录

SELECT
    *
FROM
    (
        SELECT
            *,
            ROW_NUMBER() OVER ( PARTITION BY A.ID ORDER BY EventDate DESC ) AS pc

        FROM
            SOMETABLE AS "A"
            INNER JOIN
            (
                SELECT
                    ID AS 'BID',
                    MIN(EventDate) AS 'OldestDate'
                FROM
                    SOMETABLE
                WHERE
                    TYPE = 'X' 
                GROUP BY
                    ID
            ) AS "B" ON A.ID = B.BID

    WHERE
        EventDate < OldestDate
        AND
        Type = 'Y'

    ) AS "FINAL"

在需要拉取多个类型 Y 的记录的情况下,这会失败,因为它“过滤掉”任何比类型 X 的 OLDEST 实例更新的记录。

如果给定的 X 值存在,此查询将采用最新的 Y 值。

SELECT 
    * 
    ,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY XDateTime ASC) AS 'Degree'
FROM
    (SELECT 
        *
        ,ROW_NUMBER() OVER (PARTITION BY YDateTime ORDER BY XDateTime ASC) AS 'dc'
    FROM
        (SELECT
            ID
            ,EventDateTime AS 'YDateTime'
            ,B.XDateTime
            ,DATEDIFF(SECOND, EventDateTime, B.XDateTime) AS 'Time'
            ,ROW_NUMBER() OVER (PARTITION BY B.XDateTime ORDER BY EventDateTime DESC) AS 'pc'
        
        FROM vw_A6Productivity AS "A"

        INNER JOIN
            (SELECT
                ID AS 'BID'
                ,EventDateTime AS 'XDateTime'
            
            FROM TABLE
            
            WHERE TYPE = 'X'
            
            GROUP BY 
                ID
                ,EventDateTime
            ) AS "B"

        ON A.ID= B.BID

        WHERE 
            EventDateTime < XDateTime -- Inner join filters for Nulls automatically
            AND STATUS = 'Y'
        
        ) AS "C"

    WHERE
        pc = 1
        
    ) AS "D"

WHERE dc = 1;

所以问题是寻找具有相同 ID 且密切发生的两种不同类型的事件。 不确定您是在 Y 之前寻找 X,在 X 之前寻找 Y,还是两者兼而有之。

我们可以将数据分为两组:

  • X 事件: (ID, 'X', EventDate)
  • Y 事件:(ID, 'Y', EventDate) 加入 ID 和比较 EventDate,然后根据您的条件选择一个。

步骤 1. 准备数据

create table event (
    id          int,
    event_date  date,
    type        char(1));
    

insert into event
values
(1, '2022-01-01', 'X'),
(1, '2022-01-03', 'X'),
(1, '2022-01-05', 'Y'),
(1, '2022-01-07', 'Y'),
(1, '2022-01-09', 'X'),
(1, '2022-01-11', 'X'),
(1, '2022-01-15', 'Y');

第 2 步:加入并比较两个事件

with 
event_x as (select id, type, event_date from event where type='X'),
event_y as (select id, type, event_date from event where type='Y'),
event_xy as (
select x.id,
       x.event_date as x_event_date,
       y.event_date as y_event_date,
       datediff(x.event_date,y.event_date)      as days_from_x_to_y
  from event_x x
  join event_y y
 using (id))
select id,
       x_event_date,
       y_event_date,
       days_from_x_to_y,
       abs(days_from_x_to_y) as days_between_x_and_y
  from event_xy
 where 1 = 1
   -- and days_from_x_to_y <=0   -- x happened after y
   -- and days_from_x_to_y >=0   -- x happened before y
 order by days_between_x_and_y asc;

我们得到:

id|x_event_date|y_event_date|days_from_x_to_y|days_between_x_and_y|
--+------------+------------+----------------+--------------------+
 1|  2022-01-03|  2022-01-05|              -2|                   2|
 1|  2022-01-09|  2022-01-07|               2|                   2|
 1|  2022-01-09|  2022-01-05|               4|                   4|
 1|  2022-01-01|  2022-01-05|              -4|                   4|
 1|  2022-01-11|  2022-01-07|               4|                   4|
 1|  2022-01-03|  2022-01-07|              -4|                   4|
 1|  2022-01-11|  2022-01-15|              -4|                   4|
 1|  2022-01-11|  2022-01-05|               6|                   6|
 1|  2022-01-01|  2022-01-07|              -6|                   6|
 1|  2022-01-09|  2022-01-15|              -6|                   6|
 1|  2022-01-03|  2022-01-15|             -12|                  12|
 1|  2022-01-01|  2022-01-15|             -14|                  14|

对 where 子句稍作改动,我们可以选择我们需要的 (x, y) 事件。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM