Changes between Version 3 and Version 4 of Complex DB Reports


Ignore:
Timestamp:
02/07/26 16:36:10 (21 hours ago)
Author:
231035
Comment:

--

Legend:

Unmodified
Added
Removed
Modified
  • Complex DB Reports

    v3 v4  
    22== Finding the most active users on the app during a given time period
    33This SQL query wants to find the most active users. Active are users who create listings, write reviews, handle appointments and save favorites.
     4[[BR]]
    45This query:
    56* Counts each type of activity
     
    109110{{{
    110111Period <-
    111 { (start_ts, end_ts) }
     112{(start_ts, end_ts)}
    112113
    113114ListingsByUser <-
     
    147148  user_id := f.client_id;
    148149  favorites_saved_all_time := COUNT(*)
    149 (
    150   favorite_listings f
    151 )
     150(favorite_listings f)
    152151
    153152UserActivity <-
     
    177176  appointments_cancelled := COALESCE(a.appointments_cancelled, 0),
    178177  favorites_saved_all_time := COALESCE(f.favorites_saved_all_time, 0)
    179 (
    180   UserActivity
    181 )
     178(UserActivity)
    182179
    183180ActiveUsers <-
     
    187184  appointments_total +
    188185  favorites_saved_all_time > 0
    189 (
    190   ActivityWithDefaults
    191 )
     186(ActivityWithDefaults)
    192187ScoredUsers <-
    193188π
     
    199194    favorites_saved_all_time * 1 -
    200195    appointments_no_show * 2
    201 (
    202   ActiveUsers
    203 )
     196(ActiveUsers)
    204197
    205198RankedUsers <-
     
    210203      listings_created DESC,
    211204      reviews_left DESC
    212 (
    213   ScoredUsers
    214 )
     205(ScoredUsers)
    215206Result <-
    216207τ activity_rank ASC
     
    232223    activity_score,
    233224    activity_rank
    234   (
    235     RankedUsers
    236   )
     225  (RankedUsers)
    237226)
    238227
     
    241230== Recommending listings to a user by similar users and liked listings
    242231This SQL query wants to find the recommended listings for a user based on similar users and his liked listings.
     232[[BR]]
    243233This query:
    244 *
     234* Gets the recent likes of the user
     235* Gets the similar users based on same liked listings
     236* Gets listings liked by the similar users but NOT by me
     237* Gets listings similar to my liked listings
     238* Combines them both
    245239=== SQL
    246240{{{
     241WITH
     242my_likes AS (
     243  SELECT fl.listing_id
     244  FROM favorite_listings fl
     245  WHERE fl.client_id = :user_id
     246),
     247
     248my_recent_likes AS (
     249  SELECT fl.listing_id
     250  FROM favorite_listings fl
     251  JOIN listings l ON l.listing_id = fl.listing_id
     252  WHERE fl.client_id = :user_id
     253  ORDER BY l.created_at DESC
     254  LIMIT :10
     255),
     256
     257similar_users AS (
     258  SELECT
     259    fl2.client_id AS other_user_id,
     260    COUNT(*)      AS overlap_likes
     261  FROM favorite_listings fl2
     262  JOIN my_likes ml ON ml.listing_id = fl2.listing_id
     263  WHERE fl2.client_id <> :user_id
     264  GROUP BY fl2.client_id
     265  HAVING COUNT(*) > 0
     266),
     267
     268cf_candidates AS (
     269  SELECT
     270    fl.listing_id,
     271    SUM(su.overlap_likes) AS cf_score,
     272    COUNT(DISTINCT su.other_user_id) AS liked_by_similar_users
     273  FROM similar_users su
     274  JOIN favorite_listings fl
     275    ON fl.client_id = su.other_user_id
     276  LEFT JOIN my_likes ml
     277    ON ml.listing_id = fl.listing_id
     278  WHERE ml.listing_id IS NULL 
     279  GROUP BY fl.listing_id
     280),
     281
     282content_candidates AS (
     283  SELECT
     284    l2.listing_id,
     285    COUNT(*) AS content_score
     286  FROM my_recent_likes r
     287  JOIN listings l1 ON l1.listing_id = r.listing_id
     288  JOIN listings l2 ON
     289      l2.listing_id <> l1.listing_id
     290      AND (
     291           (l2.species = l1.species)
     292        OR (l2.breed   = l1.breed)
     293        OR (l2.location = l1.location)
     294      )
     295  LEFT JOIN my_likes ml ON ml.listing_id = l2.listing_id
     296  WHERE ml.listing_id IS NULL
     297  GROUP BY l2.listing_id
     298),
     299
     300
     301merged AS (
     302  SELECT
     303    COALESCE(cf.listing_id, cc.listing_id) AS listing_id,
     304    COALESCE(cf.cf_score, 0)              AS cf_score,
     305    COALESCE(cf.liked_by_similar_users, 0) AS liked_by_similar_users,
     306    COALESCE(cc.content_score, 0)         AS content_score
     307  FROM cf_candidates cf
     308  FULL OUTER JOIN content_candidates cc
     309    ON cc.listing_id = cf.listing_id
     310)
     311
     312SELECT
     313  l.listing_id,
     314  l.title,
     315  l.species,
     316  l.breed,
     317  l.location,
     318  l.created_at,
     319
     320  m.cf_score,
     321  m.liked_by_similar_users,
     322  m.content_score,
     323
     324  (m.cf_score * 3 + m.content_score * 2) AS final_score
     325
     326FROM merged m
     327JOIN listings l ON l.listing_id = m.listing_id
     328WHERE l.status = 'ACTIVE'
     329ORDER BY final_score DESC, l.created_at DESC
     330LIMIT 20;
    247331}}}
    248332=== Relation Algebra
    249333{{{
     334Params <-
     335{(user_id := U, k_recent := 10, top_n := 20)}
     336MyLikes <-
     337π listing_id
     338(
     339  σ fl.client_id = p.user_id
     340  (
     341    favorite_listings fl × Params p
     342  )
     343)
     344MyRecentLikes <-
     345topK_{K := p.k_recent}
     346(
     347  τ l.created_at DESC
     348  (
     349    π fl.listing_id, l.created_at
     350    (
     351      σ fl.client_id = p.user_id
     352      (
     353        (favorite_listings fl ⨝ (fl.listing_id = l.listing_id) listings l)
     354        × Params p
     355      )
     356    )
     357  )
     358)
     359SimilarUsers <-
     360σ other_user_id ≠ p.user_id ∧ overlap_likes > 0
     361(
     362  γ
     363    other_user_id := fl2.client_id;
     364    overlap_likes := COUNT(*)
     365  (
     366    (
     367      favorite_listings fl2 ⨝ (fl2.listing_id = ml.listing_id) MyLikes ml
     368    )
     369    × Params p
     370  )
     371)
     372CFCandidates <-
     373γ
     374  listing_id := fl.listing_id;
     375  cf_score := SUM(su.overlap_likes);
     376  liked_by_similar_users := COUNT_DISTINCT(su.other_user_id)
     377(
     378  σ ml.listing_id IS NULL
     379  (
     380    (
     381      (SimilarUsers su ⨝ (su.other_user_id = fl.client_id) favorite_listings fl)
     382      ⟕ (fl.listing_id = ml.listing_id) MyLikes ml
     383    )
     384  )
     385)
     386
     387ContentCandidates <-
     388γ
     389  listing_id := l2.listing_id;
     390  content_score := COUNT(*)
     391(
     392  σ ml.listing_id IS NULL
     393  (
     394    (
     395      (
     396        (MyRecentLikes r ⨝ (r.listing_id = l1.listing_id) listings l1)
     397        ⨝
     398        (
     399          l2.listing_id ≠ l1.listing_id ∧
     400          (l2.species = l1.species ∨ l2.breed = l1.breed ∨ l2.location = l1.location)
     401        )
     402        listings l2
     403      )
     404      ⟕ (l2.listing_id = ml.listing_id) MyLikes ml
     405    )
     406  )
     407)
     408Merged <-
     409π
     410  listing_id := COALESCE(cf.listing_id, cc.listing_id),
     411  cf_score := COALESCE(cf.cf_score, 0),
     412  liked_by_similar_users := COALESCE(cf.liked_by_similar_users, 0),
     413  content_score := COALESCE(cc.content_score, 0)
     414(CFCandidates cf ⟗ (cf.listing_id = cc.listing_id) ContentCandidates cc)
     415FinalWithListings <-
     416π
     417  l.listing_id,
     418  l.title,
     419  l.species,
     420  l.breed,
     421  l.location,
     422  l.created_at,
     423  m.cf_score,
     424  m.liked_by_similar_users,
     425  m.content_score,
     426  final_score := (m.cf_score * 3 + m.content_score * 2)
     427(
     428  σ l.status = 'ACTIVE'
     429  ((Merged m ⨝ (m.listing_id = l.listing_id) listings l))
     430)
     431Result <-
     432topK_{N := p.top_n}
     433(
     434  τ final_score DESC, created_at DESC
     435  (FinalWithListings × Params p)
     436)
    250437
    251438}}}