我有一个问题,我需要在 PostgreSQL 的各个表中获取最后一项。
以下代码有效并向我返回最新更新的类型以及上次更新的时间。
问题是,这个查询需要用作子查询,所以我想从这个查询中选择类型和最后更新的值,而PostgreSQL似乎不喜欢这个......(Subquery must return only one column
)
有什么建议么?
SELECT last.type, last.max FROM (
SELECT MAX(a.updated_at), 'a' AS type FROM table_a a WHERE a.ref = 5 UNION
SELECT MAX(b.updated_at), 'b' AS type FROM table_b b WHERE b.ref = 5
) AS last ORDER BY max LIMIT 1
Query 在 CTE 中是这样使用的;
WITH sql_query as (
SELECT id, name, address, (...other columns),
last.type, last.max FROM (
SELECT MAX(a.updated_at), 'a' AS type FROM table_a a WHERE a.ref = 5 UNION
SELECT MAX(b.updated_at), 'b' AS type FROM table_b b WHERE b.ref = 5
) AS last ORDER BY max LIMIT 1
FROM table_c
WHERE table_c.fk_id = 1
)
固有的问题是 SQL(所有 SQL 不仅仅是 Postgres)要求在 select 子句中使用的子查询只能返回一个值。如果你考虑一下这个限制,它确实是有道理的。select 子句返回行和一定数量的列,每个 row.column 位置是网格中的一个位置。您可以通过将连接放入单个位置(或单个“复杂类型”,如 JSON 值)来稍微改变该规则,但无论如何它仍然是该网格中的单个位置。
但是,在这里您确实需要 2 个单独的列,并且您需要从同一行返回两列,因此LIMIT 1
我建议使用ROW_NUMBER()
代替来促进这一点:
WITH LastVals as (
SELECT type
, max_date
, row_number() over(order by max_date DESC) as rn
FROM (
SELECT MAX(a.updated_at) AS max_date, 'a' AS type FROM table_a a WHERE a.ref = 5
UNION ALL
SELECT MAX(b.updated_at) AS max_date, 'b' AS type FROM table_b b WHERE b.ref = 5
)
)
, sql_query as (
SELECT id
, name, address, (...other columns)
, (select type from lastVals where rn = 1) as last_type
, (select max_date from lastVals where rn = 1) as last_date
FROM table_c
WHERE table_c.fk_id = 1
)
顺便说一下,在您的子查询中,您应该使用UNION ALL
type 作为常量,例如 'a' 或 'b' 那么即使MAX(a.updated_at)
对于 2 个或更多表是相同的,由于类型不同,行仍然是唯一的。UNION
将尝试删除重复的行,但在这里它不会有帮助,所以通过使用UNION ALL
.
另一种方式对皮肤这只猫,可以考虑使用LEFT JOIN
替代
SELECT id
, name, address, (...other columns)
, lastVals.type
, LastVals.last_date
FROM table_c
WHERE table_c.fk_id = 1
LEFT JOIN (
SELECT type
, last_date
, row_number() over(order by last_date DESC) as rn
FROM (
SELECT MAX(a.updated_at) AS last_date, 'a' AS type FROM table_a a WHERE a.ref = 5
UNION ALL
SELECT MAX(b.updated_at) AS last_date, 'b' AS type FROM table_b b WHERE b.ref = 5
)
) LastVals ON LastVals.rn = 1
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句