简体   繁体   中英

Postgresql computed column

I have a question, that I did not found answer for it.

Here an example:

Table: interests

  • id: integer - primary key
  • name: interest name - unique
  • popularity: interest popularity

Table: users

  • id: integer - primary key
  • email: string - unique
  • interests: array of integer - foreign keys of 'interests' table

I want the 'popularity' column of 'interests' table to be computed thanks to the 'users' table.

Table users

  id | email           | interests
  0  | toto0.gmail.com | [ 0 ]
  1  | toto1.gmail.com | [ 0, 1 ]
  2  | toto2.gmail.com | [ 1 ]
  3  | toto2.gmail.com | [ 2 ]

Table interests

  id | name         | popularity
  0  | 'interest 0' | 2
  1  | 'interest 1' | 2
  2  | 'interest 2' | 1
  3  | 'interest 3' | 0

I have tried this:

  UPDATE interests SET popularity = (SELECT COUNT(*) from public.users where ARRAY[interests] @> ARRAY[interests.id]);

But I don't want to run a query to update the interests table. I mean, I want the 'popularity' column to be filled automatically when a user subscribes to it.

If I create a 'view' like this, it should work as I want ?

  CREATE VIEW interests_popularity (id, popularity) AS
     SELECT COUNT(1) as popularity, interest.id
     FROM public.user, interest
     WHERE ARRAY[public.user.interests] @> ARRAY[interest.id]
     GROUP BY interest.id;

Is there a more efficient way to do that ?

Konstantin's suggestion was to use a trigger to increase popularity in the "interests" table every time a user subscribes to a particular interest. That can be efficient enough, until too many sessions wait on row-level lock on a particular interest that is being updated by multiple sessions.

If you dropped the uniqueness constraint on the table "interests", you could record new subscriptions on the fly with an insert that would block nothing. To fetch overall statistics you would have to do SELECT id, count(*) FROM interests GROUP BY id , which may be fast enough for you if you periodically update the whole table to regroup it to eliminate duplicates.

I have changed my model to handle this problem.

There is a separated table, and when I need to get an interest by popularity I just have to count on a 'UNIQUE' key.

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