我们正在运行此查询:
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 中实现这一目标的最佳方法吗?
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;
case when x is null then y else x end
翻译为 coalesce(x,y)
to_char()
,则 null
函数将返回 null
join using
为您保存方程式并合并同名列编程方面的要求需要精确。
您的标准在三个主要方面不明确:
从中检索最新的推荐值
表,其中推荐值recommendations_history
。<>current_recommendation
这可以用两种有意义的不同方式翻译:
你让它听起来像recommendations_history
中的
any行都是候选者,而我很确定你只想考虑相关行 - 在这种情况下你需要定义关系。我会假设列中还有另一场比赛
ticker
?
如果 (
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
的内容。
尝试一下,我引入了
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;