SQL查询以基于同一表中的另一行检索行

时间:2011-05-19 13:27:36

标签: sql postgresql

我的表格statuses包含idnameparent_id列。

我想检索一行parent_id = 9 如果没有这样的行,我想获得id = 9行。

我可以通过单一查询得到这个吗?

5 个答案:

答案 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更新帖子,结果会更快,那就太好了。

  1. SELECT VERSION();
  2. SELECT COUNT(*)FROM status;
  3. 来自EXPLAIN ANALYZE $ {QUERY};
  4. 的最后一行

答案 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);

..在没有索引的表上可能会更快。