skip to Main Content

We have this query that is running:

     SELECT concat_ws(' ', z.ticker,
            CASE
              WHEN a.date_approved IS NOT NULL THEN TO_CHAR(a.date_approved,'YYMMDD')
              WHEN z.date_recommended IS NULL THEN '000000'
              ELSE TO_CHAR(z.date_recommended,'YYMMDD')
            END,
             CASE
               WHEN s.ticker IS NOT NULL THEN 6
               WHEN a.approved_recommendation IS NOT NULL THEN approved_recommendation
               ELSE current_recommendation
             END,
             REPLACE(CASE
                       WHEN comments IS NULL THEN 'N/C'
                       ELSE comments
                     END,' ','_'))
     FROM recommendations z
     LEFT JOIN (SELECT ticker FROM scr_tickers) s
            ON z.ticker = s.ticker
     LEFT JOIN (SELECT ticker, date_approved, approved_recommendation
                FROM approved_recommendations) a
            ON z.ticker = a.ticker
     WHERE z.ticker NOT LIKE 'T.%'
       AND z.ticker NOT LIKE 'V.%'
     ORDER BY z.ticker;

Now, they want to add another data item after the comments, which is to retrieve the most recent recommendation value from the recommendations_history table, where the recommendation value <>current_recommendation.

In order to do that, I can do a join, use ROW_NUMBER with an ORDER BY and choose the first row. Is that the best way to achieve this in PostgreSQL?

2

Answers


  1. Try this, I introduced a LEFT JOIN to incorporate the most recent recommendation from the recommendations_history table that differs from the current recommendation in the recommendations table. This is achieved by joining a subquery that employs the ROW_NUMBER() window function, partitioned by ticker and ordered by the recommendation date in descending order.

    SELECT concat_ws(' ', 
                     z.ticker,
                     CASE
                       WHEN a.date_approved IS NOT NULL THEN TO_CHAR(a.date_approved,'YYMMDD')
                       WHEN z.date_recommended IS NULL THEN '000000'
                       ELSE TO_CHAR(z.date_recommended,'YYMMDD')
                     END,
                     CASE
                       WHEN s.ticker IS NOT NULL THEN 6
                       WHEN a.approved_recommendation IS NOT NULL THEN a.approved_recommendation
                       ELSE z.current_recommendation
                     END,
                     REPLACE(CASE
                                 WHEN z.comments IS NULL THEN 'N/C'
                                 ELSE z.comments
                               END, ' ', '_'),
                     COALESCE(rh.recommendation, 'No Recent Recommendation')
                   )
    FROM recommendations z
    LEFT JOIN (SELECT ticker FROM scr_tickers) s ON z.ticker = s.ticker
    LEFT JOIN (SELECT ticker, date_approved, approved_recommendation
               FROM approved_recommendations) a ON z.ticker = a.ticker
    LEFT JOIN (SELECT ticker, recommendation, ROW_NUMBER() OVER (PARTITION BY ticker ORDER BY recommendation_date DESC) AS rn
               FROM recommendations_history
               WHERE recommendation <> (SELECT current_recommendation FROM recommendations WHERE ticker = recommendations_history.ticker)
              ) rh ON z.ticker = rh.ticker AND rh.rn = 1
    WHERE z.ticker NOT LIKE 'T.%'
      AND z.ticker NOT LIKE 'V.%'
    ORDER BY z.ticker;
    
    Login or Signup to reply.
  2. SELECT concat_ws(' ', z.ticker,
            COALESCE(TO_CHAR(a.date_approved,'YYMMDD'),
                     TO_CHAR(z.date_recommended,'YYMMDD'),
                     '000000'),
             CASE WHEN s.ticker IS NOT NULL THEN 6
                  ELSE COALESCE(a.approved_recommendation, current_recommendation)
             END,
             REPLACE(COALESCE(comments,'N/C'),' ','_'),
             rh.recommendation_value)
     FROM recommendations z
     LEFT JOIN (SELECT ticker FROM scr_tickers) s
            USING (ticker)
     LEFT JOIN (SELECT ticker, date_approved, approved_recommendation
                FROM approved_recommendations) a
            USING (ticker)
     LEFT JOIN (SELECT rh.ticker, rh.recommendation_value
                FROM recommendations_history rh
                WHERE z.current_recommendation<>rh.recommendation_value
                ORDER BY submit_date DESC LIMIT 1) rh
            USING (ticker)
     WHERE z.ticker NOT LIKE 'T.%'
       AND z.ticker NOT LIKE 'V.%'
     ORDER BY z.ticker;
    
    1. case when x is null then y else x end translates to coalesce(x,y)
    2. to_char() function returns null if it gets null on input
    3. join using saves you equations and coalescing same-name columns
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search