我的表格statuses
包含id
,name
和parent_id
列。
我想检索一行parent_id = 9
如果没有这样的行,我想获得id = 9
行。
我可以通过单一查询得到这个吗?
答案 0 :(得分:2)
您可以选择这两行,在顶部订购parent_id
个匹配项,然后抓住第一行:
select *
from statuses
where parent_id = 9 or id = 9
order by
case when parent_id = 9 then 1 else 2 end
limit 1
如果id
不是主键,您可以尝试union
,只有在前半部分为空时才执行后半部分:
select *
from statuses
where parent_id = 9
union all
select *
from statuses
where id = 9
and not exists
(
select *
from statuses
where parent_id = 9
)
答案 1 :(得分:2)
SELECT
ISNULL(SP.id, S.parent_id)
FROM
Statuses S
LEFT JOIN
Statuses SP on S.parent_id=SP.id
WHERE
S.parent_id = 9
答案 2 :(得分:1)
@ Andomar的答案都可行。一旦填充了表格,请务必使用EXPLAIN ANALYZE来确定哪一个实际上更快。事实上,如果您可以根据少数EXPLAIN ANALYZE更新帖子,结果会更快,那就太好了。
答案 3 :(得分:0)
select * from statuses
where parent_id = 9 or id = 9
order by case when parent_id = 9 then 1 else 2 end
limit 1
答案 4 :(得分:0)
更简单,更快:
SELECT * FROM COALESCE(
(SELECT s FROM statuses s WHERE parent_id = 9 LIMIT 1)
,(SELECT s FROM statuses s WHERE id = 9 LIMIT 1)
)
如果不存在任何ID,则此查询将返回填充statuses
值的NULL
行,而此处的其他解决方案到目前为止返回 no row 。因为这就是你打电话时发生的事情
SELECT * FROM NULL::statuses
。
COALESCE
本身不能在rows
上运行,代替变量的子查询只能返回一列。如果您尝试:
SELECT COALESCE(
(SELECT * FROM statuses WHERE parent_id = 9 LIMIT 1)
,(SELECT * FROM statuses WHERE id = 9 LIMIT 1)
)
你得到了
错误:子查询必须只返回一列
但是,对于PostgreSQL中的每个表,都存在同名的复合类型。您可以让子查询将整行作为复合类型返回,然后展开类型。这就是查询的作用。
我使用PostgreSQL 9.1.4中70k行的类似真实表运行快速基准测试,两个唯一ID列索引。我测试了所有三种情况:parent_id
存在,id
存在,不存在。此查询比其他解决方案略快。我还尝试了一个固定的等效@ Parkyprg的错误答案和@Endy和@Andomar发布的简化版本:
SELECT *
FROM statuses
WHERE parent_id = 9 OR id = 9
ORDER BY (id <> 9);
..在没有索引的表上可能会更快。