Question

I have a Clients table in PostgreSQL (version 9.1.11), and I would like to write a query to filter that table. The query should return only clients which meet one of the following conditions:

--The client's last order (based on orders.created_at) has a fulfill_by_date in the past.

OR

--The client has no orders at all

I've looked for around 2 months, on and off, for a solution.

I've looked at custom last aggregate functions in Postgres, but could not get them to work, and feel there must be a built-in way to do this.

I've also looked at Postgres last_value window functions, but most of the examples are of a single table, not of a query joining multiple tables.

Any help would be greatly appreciated! Here is a sample of what I am going for:

Clients table:  
| client_id | client_name  |
----------------------------
| 1         | FirstClient  |
| 2         | SecondClient |
| 3         | ThirdClient  |
Orders table:
| order_id | client_id | fulfill_by_date | created_at |
-------------------------------------------------------
| 1        | 1         | 3000-01-01      | 2013-01-01 |
| 2        | 1         | 1999-01-01      | 2013-01-02 |
| 3        | 2         | 1999-01-01      | 2013-01-01 |
| 4        | 2         | 3000-01-01      | 2013-01-02 |
Desired query result:
| client_id | client_name  |
----------------------------
| 1         | FirstClient  |
| 3         | ThirdClient  |
Was it helpful?

Solution

Try it this way

SELECT c.client_id, c.client_name
  FROM clients c LEFT JOIN
(
  SELECT *, ROW_NUMBER() OVER (PARTITION BY client_id ORDER BY created_at DESC) rnum
    FROM orders
) o 
    ON c.client_id = o.client_id
   AND o.rnum = 1
 WHERE o.fulfill_by_date < CURRENT_DATE
    OR o.order_id IS NULL

Output:

| CLIENT_ID | CLIENT_NAME |
|-----------|-------------|
|         1 | FirstClient |
|         3 | ThirdClient |

Here is SQLFiddle demo

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top