简体   繁体   中英

(SQL - Snowflake) How do I query a series of events to where it only pulls the first and last event?

I'm looking to query event history (project with lots of tasks and subtasks) to where it only pulls the first and last event on a given task's history and none of the ones in between.

Right now, I can't find another way to compare originating event based IDs (original task:subtask pair) and what the IDs currently are (sometimes they change based on what happens to the tasks when they're moving between queues).

This is the main chunk of query I'm working on.

The current "completed_at" strings I have trust issues with, so I want to change to using work_time (basically an in depth audit log), but I only want the MIN and MAX time.

Is this something I can do without it being an actual column?

select
    pt._id as t_id,
    ps._id as st_id,
    pt.completed_at as t_completed_at,
    pt.first_completed_at as t_first_completed_at,
    ps.completed_at as ps_completed_at,
    pt.times_redone,
    ps.is_recalled_subtask as ps_recalled,
    ps.status,
    ps.review_level,
    pt.customer_review_status,
    pt.customer_review_comments,
    array_size(ps.response:annotations),
    ps.subtask_version,
    vfwa.FIX_ATTEMPT,
    vfwa.work_time as time_attempt_was_completed

You can use QUALIFY to remove rows that you don't want, after having access to them to allow window processing (like SUM, MAX, etc)

SELECT 
    t.order_val, 
    t.thing_a, 
    t.thing_b
FROM VALUES
    (1,'this is first', 'extra details'),
    (2,'this is second', 'hate to middle things'),
    (3,'this is third', 'hate to middle things'),
    (4,'this is firth', 'last this are as good as first')
    t(order_val, thing_a, thing_b)
QUALIFY order_val = max(order_val)over() OR order_val = min(order_val)over();

gives:

ORDER_VAL THING_A THING_B
1 this is first extra details
4 this is firth last this are as good as first

The classic QUALIFY pattern uses ROW_NUMBER, would look like:

QUALIFY row_number()over(order by order_val) = 1 OR row_number()over(order by order_val DESC) = 1

But if you have calculated values if your values, you can use it like a bonus WHERE clause that is run after all the GROUPING has been done.

MATCH_RECOGNIZE was created for this:

select * from stock_price_history
  match_recognize(
    partition by company
    order by price_date
    measures
      first(price_date) as start_date,
      last(price_date) as end_date,
      first(price) as start_price,
      last(price) as end_price
    one row per match
    pattern(x*)
    define
        t as true
  )
order by company;

Basically with partition you can divide by task, and first() and last() will bring the ids or values you need to identify the first and last row for a series of events.

在此处输入图像描述

Setup:

create table stock_price_history (company text, price_date date, price int);
insert into stock_price_history values
    ('ABCD', '2020-10-01', 50),
    ('XYZ' , '2020-10-01', 89),
    ('ABCD', '2020-10-02', 36),
    ('XYZ' , '2020-10-02', 24),
    ('ABCD', '2020-10-03', 39),
    ('XYZ' , '2020-10-03', 37),
    ('ABCD', '2020-10-04', 42),
    ('XYZ' , '2020-10-04', 63),
    ('ABCD', '2020-10-05', 30),
    ('XYZ' , '2020-10-05', 65),
    ('ABCD', '2020-10-06', 47),
    ('XYZ' , '2020-10-06', 56),
    ('ABCD', '2020-10-07', 71),
    ('XYZ' , '2020-10-07', 50),
    ('ABCD', '2020-10-08', 80),
    ('XYZ' , '2020-10-08', 54),
    ('ABCD', '2020-10-09', 75),
    ('XYZ' , '2020-10-09', 30),
    ('ABCD', '2020-10-10', 63),
    ('XYZ' , '2020-10-10', 32);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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