Home > Enterprise >  PSQL: How to compare record to previous record (2 tables)?
PSQL: How to compare record to previous record (2 tables)?

Time:04-09

I have two tables:

01_System_Log

request_date   request_id
2022-01-01     1
2022-01-10     2
2022-01-20     3

Records

firm    name    city  request_id

firm_a  John    NY              1
firm_b  Will    LA              1
firm_c  Andy    SF              1
firm_c  Marga   CH              1

firm_a  John    NY              2
firm_b  Will    LA              2
firm_b  Nancy   LA              2
firm_c  Andy    SF              2
firm_c  Marga   CH              2

firm_a  John    NY              3
firm_b  Will    CH              3
firm_b  Nancy   LA              3
firm_c  Andy    SF              3
firm_c  Marga   SF              3 
firm_c  Joe     SF              3 

I need to create a view, where the records of the last request id (3) are compared with the previous (2). So far I made a view, where the most actual records are shown.

SELECT DISTINCT main.firm,
    main.name,
    main.city,
    sys_log.request_id,
FROM "Records" main
INNER JOIN ( 
    SELECT sys.request_date,
           sys.request_id
    FROM "01_System_Log" sys
    ORDER BY sys.request_id DESC
    LIMIT 1 ) sys_log ON sys_log.request_id = main.request_id
WHERE  main.request_id IS NOT NULL
ORDER BY main.firm;

I am not sure how to proceed, while in all compare examples, which I have found, only one table was used.

My ideal result is:

firm   name_    city  request_id  firm_n name_n  city_n  request_id_n

firm_a  John     NY    2          firm_a  John     NY    3
firm_b  Will     LA    2          firm_b  Will     CH    3
firm_b  Nancy    LA    2          firm_b  Nancy    LA    3
firm_c  Andy     SF    2          firm_c  Andy     SF    3
firm_c  Marga    CH    2          firm_c  Marga    SF    3 
                                  firm_c  Joe      SF    3

CodePudding user response:

The information is all coming from one table "Records" so you just need to include that table twice in your query, using appropriate aliases, once to get the records with the highest request_id and once for the request_id which is lower than the highest. Finally you need to find what the highest request_id is, which you can do with a CTE on the "01_System_Log" table.

The CTE is straightforward:

WITH highest AS (
    SELECT request_id AS id
    FROM "01_System_Log"
    ORDER BY request_date DESC LIMIT 1
)

The records that use the highest request_id are also easily found:

SELECT firm, name, city, request_id
FROM "Records"
JOIN highest ON "Records".request_id = highest.id

To get the records with the second highest request_id for each combination of firm and city you need to use a window function:

SELECT DISTINCT firm, name, 
       first_value(city) OVER w AS city, 
       first_value(request_id) OVER w AS request_id
FROM "Records"
JOIN highest ON "Records".request_id < highest.id -- exclude the highest request_id
WINDOW w AS (PARTITION BY (firm, name) ORDER BY request_id DESC
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)

And then you tie it all together with sub-queries (and removing columns with duplicate information):

WITH highest AS (
    SELECT request_id AS id
    FROM "01_System_Log"
    ORDER BY request_date DESC LIMIT 1
)
SELECT curr.firm, curr.name, 
       prev.city AS previous_city, prev.request_id AS previous_request_id,
       curr.city AS current_city, curr.request_id AS current_request_id
FROM (
    SELECT DISTINCT firm, name, 
           first_value(city) OVER w AS city, 
           first_value(request_id) OVER w AS request_id
    FROM "Records"
    JOIN highest ON "Records".request_id < highest.id
    WINDOW w AS (PARTITION BY (firm, name) ORDER BY request_id DESC
        ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) ) prev
RIGHT JOIN (
    SELECT firm, name, city, request_id
    FROM "Records"
    JOIN highest ON "Records".request_id = highest.id ) curr USING (firm, name)
ORDER BY curr.firm;

  • Related