SQL 查询根据同一表中的另一行检索一行

发布于 2024-11-08 14:15:18 字数 198 浏览 0 评论 0 原文

我有一个表 statuses,其中包含 idnameparent_id 列。

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

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

I have a table statuses with columns id, name and parent_id.

I want to retrieve a row with parent_id = 9.
If there is not such a row, I want to get the row with id = 9.

Can I get this with single query?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

叫嚣ゝ 2024-11-15 14:15:18

您可以选择这两行,将 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< /code> 其中仅当前半部分为空时才执行后半部分:

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
        )

You could select both rows, order the parent_id matches on top, and grab the top row:

select  *
from    statuses
where   parent_id = 9 or id = 9
order by
        case when parent_id = 9 then 1 else 2 end
limit   1

If id is not a primary key, you could try a union where the second half is only executed if the first half is empty:

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
        )
说谎友 2024-11-15 14:15:18
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
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
悟红尘 2024-11-15 14:15:18

@Andomar 的任何一个答案都可以。请务必使用 EXPLAIN ANALYZE 来找出哪一个是一旦你的表被填充,实际上会更快。事实上,如果您可以根据一些 解释分析

  1. 选择版本();
  2. 从状态中选择 COUNT(*) 个;
  3. EXPLAIN ANALYZE ${QUERY}; 的最后一行

Either of @Andomar's answers will work. Just be sure to use EXPLAIN ANALYZE to figure out which one is actually faster once you have your table populated. In fact, it would be nice if you could update your post with the results of which was faster based on a few EXPLAIN ANALYZE's.

  1. SELECT VERSION();
  2. SELECT COUNT(*) FROM statuses;
  3. And the last line from EXPLAIN ANALYZE ${QUERY};
鸩远一方 2024-11-15 14:15:18
select * from statuses
  where parent_id = 9 or id = 9
  order by case when parent_id = 9 then 1 else 2 end
  limit 1
select * from statuses
  where parent_id = 9 or id = 9
  order by case when parent_id = 9 then 1 else 2 end
  limit 1
红衣飘飘貌似仙 2024-11-15 14:15:18

更简单、更快:

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行。因为这就是当你打电话时会发生的事情
从 NULL::statuses 中选择 *

说明

COALESCE 本身无法对 进行操作,代替变量的子查询预计仅返回一列。如果你尝试:

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

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

Simpler, faster:

SELECT * FROM COALESCE(
     (SELECT s FROM statuses s WHERE parent_id = 9 LIMIT 1)
    ,(SELECT s FROM statuses s WHERE id = 9 LIMIT 1)
    )

If none of the IDs exist, this query returns a row of type statuses filled with NULL values, while the other solutions here so far return no row. Because that's what happens when you call
SELECT * FROM NULL::statuses.

Explanation

COALESCE cannot operate on rows per se, a sub-query in place of a variable is expected to return one column only. If you try:

SELECT COALESCE(
     (SELECT * FROM statuses WHERE parent_id = 9 LIMIT 1)
    ,(SELECT * FROM statuses WHERE id = 9 LIMIT 1)
    )

You get

ERROR: subquery must return only one column

However, for every table in PostgreSQL a composite type of the same name exists. You can have the subqueries return the whole row as composite type and expand the type afterwards. That's what the query does.

I ran a quick benchmark with a similar real life table of 70k rows in PostgreSQL 9.1.4, both unique ID columns indexed. I tested all three cases: parent_id exists, id exists, none exists. This query is slightly faster than other solution here. I also tried a fixed equivalent of @Parkyprg's incorrect answer and a simplified version of what @Endy and @Andomar posted:

SELECT  *
FROM    statuses
WHERE   parent_id = 9 OR id = 9
ORDER   BY (id <> 9);

.. which could be faster on tables without indexes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文