Search code examples
sqlpostgresqlpostgresql-12

Running the definition of a view returns different results to running the view itself


I am currently using PostgreSQL 12.11 and have a view called previous_customers with the following definition (extracted from DDL):

CREATE VIEW previous_customers(customer_id, alumni) as
SELECT DISTINCT purchase.customer_id,
                true AS alumni
FROM purchase p
WHERE (purchase.purchase_state = 'paid'
   OR ((SELECT count(*) AS count
        FROM purchase
        WHERE (purchase.purchase_state NOT IN ('annulled', 'cancelled'))
          AND purchase.customer_id = p.customer_id) > 1));

This view works fine, however the issue arises when I compare the results of this view with an identical query:

WITH customer_alu as(
SELECT DISTINCT purchase.customer_id,
                true AS alumni
FROM purchase p
WHERE (purchase.purchase_state = 'paid'
   OR ((SELECT count(*) AS count
        FROM purchase
        WHERE (purchase.purchase_state NOT IN ('annulled', 'cancelled'))
          AND purchase.customer_id = p.customer_id) > 1)))

SELECT customer_alu.customer_id FROM customer_alu
WHERE customer_alu.customer_id NOT IN 
  (SELECT previous_customers.customer_id FROM public.previous_customers);

As both the CTE customer_alu and view previous_customers are identical I would imagine this query would return nothing, however I get 30 customer_id's. I am pretty stumped as to how this could happen.

From the Postgres docs:

CREATE VIEW defines a view of a query. The view is not physically materialized. Instead, the query is run every time the view is referenced in a query. link

This leads me to expect that both the view and CTE should execute identical queries, and return the same results.

Any help is appreciated.


Solution

  • The query results differed because of a create_views script, which created the view with an outdated definition. This view was then contrasting with the cached object on my connection to the Postgres DB. I noticed this after refreshing my connection to the DB and getting a conflict warning. The solution was to edit the create_views script and re-run it.