加入单个最新行

问题描述 投票:0回答:3

我们正在运行此查询:

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;

现在,他们想在

comments
之后添加另一个数据项,即从
recommendations_history
表中检索最新的推荐值,其中推荐值
<>current_recommendation

为此,我可以执行

join
,将
ROW_NUMBER
ORDER BY
一起使用,然后选择第一行。这是在 PostgreSQL 中实现这一目标的最佳方法吗?

sql postgresql subquery left-join greatest-n-per-group
3个回答
0
投票
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
    翻译为
    coalesce(x,y)
  2. 如果输入时获得
  3. to_char(),则
    null
     函数将返回 
    null
  4. join using
    为您保存方程式并合并同名列

0
投票

编程方面的要求需要精确。
您的标准在三个主要方面不明确

从中检索最新的推荐值

recommendations_history
表,其中推荐值
<>current_recommendation

  1. 这可以用两种有意义的不同方式翻译:

    • 1a。 获取最新的推荐,然后检查是否有不同。
    • 1b。 获取同样不同的最新推荐。
  2. 你让它听起来像recommendations_history中的

    any
    行都是候选者,而我很确定你只想考虑相关行 - 在这种情况下你需要定义关系。我会假设列中还有另一场比赛
    ticker

  3. 如果 (

    recommendation
    ,
    current_recommendation
    ,
    date_recommended
    ) 中的任何一个可以为空,则此加法将产生令人惊讶的结果。您需要排除空值或公开
    CREATE TABLE
    语句并定义所需的行为。我会假设所有涉及的列都是
    NOT NULL

我将使用相关子查询实现变体 1a

SELECT concat_ws(' '
         , r.ticker
         , COALESCE(to_char(COALESCE(a.date_approved, z.date_recommended),'YYMMDD'), '000000')
         , CASE WHEN s.ticker IS NOT NULL THEN 6 ELSE COALESCE(a.approved_recommendation, r.current_recommendation) END
         , COALESCE(translate(r.comments, ' ', '_') 'N/C')
         , (SELECT h.recommendation
            FROM   recommendations_history h
            WHERE  h.ticker = r.ticker
            AND    h.recommendation <> r.current_recommendation  --!?
            ORDER  BY h.date_recommended DESC
            LIMIT  1)
         ) AS my_field_name
FROM   recommendations r
LEFT   JOIN scr_tickers s USING (ticker)
LEFT   JOIN approved_recommendations a USING (ticker)
WHERE  r.ticker !~ '^[TV]\.'
ORDER  BY r.ticker;

对于变体 1b,我们必须检查 after 找到最新行,因此使用

LATERAL
子查询:

SELECT concat_ws(' '
         , r.ticker
         , COALESCE(to_char(COALESCE(a.date_approved, z.date_recommended),'YYMMDD'), '000000')
         , CASE WHEN s.ticker IS NOT NULL THEN 6 ELSE COALESCE(a.approved_recommendation, r.current_recommendation) END
         , COALESCE(translate(r.comments, ' ', '_') 'N/C')
         , h.recommendation
         ) AS my_field_name
FROM   recommendations r
LEFT   JOIN scr_tickers s USING (ticker)
LEFT   JOIN approved_recommendations a USING (ticker)
LEFT   JOIN LATERAL (  -- must be LATERAL!
   SELECT h.recommendation
   FROM   recommendations_history h
   WHERE  h.ticker = r.ticker
   ORDER  BY h.date_recommended DESC
   LIMIT  1
   ) h ON h.recommendation <> r.current_recommendation
WHERE  r.ticker !~ '^[TV]\.'
ORDER  BY r.ticker;

参见:

WHERE  r.ticker !~ '^[TV]\.'
(可选)包装您的两个
LIKE
谓词。

另外,Frank已经评论了毫无意义的子查询,以及Zegarek已经提供了关于

COALESCE
的内容。


-1
投票

尝试一下,我引入了

LEFT JOIN
来合并
recommendations_history
表中与建议表中当前建议不同的最新建议。这是通过加入使用
ROW_NUMBER()
窗口函数的子查询来实现的,该子查询按代码分区并按推荐日期降序排列。

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;
© www.soinside.com 2019 - 2024. All rights reserved.