简体   繁体   中英

using 'parititon by' and window functions to return more then one row in postgres?

:)

I'm learning Postgresql, working with version 11.4

there are rows in my table that relate to other rows by their common id (lets call the column common_id ) and by direction ( 1 or 2 ).

each common_id can and must have only one direction 1 , it can have 0 to 10 rows from direction 2 .

the table is huge so I don't want to join to the same table, I have two scenarios, I solved one.. didn't solve the other.

so lets say I have the following table:

common_id | direction | price | time 
1           1           0       1
2           1           1       4
2           2           2.5     5
3           1           5       8
3           2           7       10
3           2           10      12

so the first scenario is to connect the row with direction 1 to the row of direction 2 with the newest time. of course all in the same common_id .

so here I can just do PARTITION BY common_id order by direction, time RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING and the first_value() is the line with direction 1 and last_value() is the line with direction 2 if the count(1) is greater then 1, if not then there is no direction 2 .

so this is the result:

common_id  | price_1 | time_1 | price_2 | time_2
1            0         1        null      null
2            1         4        2.5       5
3            5         8        10        12

this work blazing fast and I'm happy. so here for every common_id I have one line. but what happens when I need to have more then one line for each partition ?

the 2nd scenario is that I need to get for each common_id all the lines with direction 2 and to connect to each of the lines the row with same common_id with direction 1 .

so here the expected result should be:

common_id  | price_1 | time_1 | price_2 | time_2
2            1         4        2.5       5
3            5         8        7         10
3            5         8        10        12

I would love if there is a way to resolve it using PARTITION BY, if not some other solution but I cannot use another join to that same table because of performance issue since it's a really huge table.

I hope I explained myself properly.

thank you

Try this (untested) query:

SELECT common_id,
       price_1,
       time_1,
       price_2,
       time_2
FROM (SELECT common_id,
             direction,
             first_value(price) OVER w AS price_1,
             first_value(time) OVER w AS time_1,
             price AS price_2,
             time AS time_2
      FROM atable
      WINDOW w AS (PARTITION BY common_id
                   ORDER BY direction
                   ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
     ) q
WHERE direction = 2;

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