In a PostgreSQL 9.5.3 DB, I have a credit_card_balances table referencing a persons table which tracks the balances of various credit cards associated to a particular person:
CREATE TABLE persons (
  id serial PRIMARY KEY,
  name text
);
CREATE credit_card_balances (
  id serial PRIMARY KEY,
  card_provider text, 
  person int REFERENCES persons,
  balance decimal, 
  timestamp timestamp
);
Example row for credit_card_balances:
id  |  card_provider | person  | balance | timestamp
123 |  visa          | 1234    | 1.00    | 16-07-26 17:00
I need to retrieve the collection of people who have both a 'visa' and an 'amex' card, such that the most recent balance on the 'visa' card is larger than the most recent balance on the 'amex' card.
For each (person, card_provider) there may be up to around 100 rows in the table. Ideally, the output columns would be:
person, provider1_balance, provider2_balance, provider1_timestamp, provider2_timestamp
I know that I can do something like
SELECT DISTINCT ON (card_provider) *
FROM credit_card_balances 
WHERE person=1234
ORDER BY card_provider, timestamp DESC;
to get the most recent balances for each card for a particular person. But I'm not sure how to do that over all people and verify the conditions above, or if this is even the correct approach.
Edit: AS partially suggested in an answer, I can also do something like
SELECT * from credit_card_balances b1, credit_card_balances b2
WHERE b1.person = b2.person
AND (b1.card_provider = 'amex' 
     AND b1.timestamp in
        (SELECT MAX(time_stamp) 
         FROM credit_card_balances 
         WHERE card_provider = 'amex'))
AND (b2.card_provider = 'visa'
     AND <... same as above>)
AND b1.balance > b2.balance;
But I noticed that this leads to horrible performance. So I think this isn't such a good option.
 
     
     
     
    