当前位置: 首页 > 知识库问答 >
问题:

如何选择具有左外连接的最小UUID?

仉刚洁
2023-03-14

我正在尝试从表中选择一行,其中:

  1. 具有最小UUID
  2. 未在其他表中引用

但是,当我试图实施第一个约束时,我遇到了问题。

下面是在整数上按预期工作的所有内容:首先,创建如下所示的表:

t1
+----+---------+
| id | content |
+----+---------+
|  1 | a       |
|  2 | b       |
|  3 | c       |
+----+---------+

t2
+----+---------+
| id | t1_id   |
+----+---------+
|  1 | 1       |
+----+---------+
postgres=# create table t1(id int, content varchar(10), primary key (id));
CREATE TABLE
postgres=# create table t2(id int, t1_id int, foreign key (t1_id) references t1(id));
CREATE TABLE
postgres=# insert into t1 values (1, 'a');
INSERT 0 1
postgres=# insert into t1 values (2, 'b');
INSERT 0 1
postgres=# insert into t1 values (3, 'c');
INSERT 0 1
postgres=# insert into t2 values (1, 1);
INSERT 0 1

现在,我想选择t1中具有最低id的行,它在t2中不显示为外键。我想选择t1中具有id=2并且按预期工作的行:

postgres=# select min(t1.id) from t1 left outer join t2 on t1.id = t2.t1_id where t2.id is null;
 min
-----
   2
(1 row)

但是,当我对UUID进行同样的尝试时,最终查询根本无法返回任何内容。请注意,我已经使用这篇文章的答案来定义一种查找最小UUID的方法:

CREATE OR REPLACE FUNCTION min(uuid, uuid)
RETURNS uuid AS $$
BEGIN
    IF $2 IS NULL OR $1 > $2 THEN
        RETURN $2;
    END IF;

    RETURN $1;
END;
$$ LANGUAGE plpgsql;


create aggregate min(uuid) (
  sfunc = min,
  stype = uuid,
  combinefunc = min,
  parallel = safe,
  sortop = operator (<)
);

现在,像以前一样构建表,使用gen\u random\u uuid自动生成uuid:

postgres=# drop table t2;
postgres=# drop table t1;
postgres=# create table t1(id uuid default gen_random_uuid(), content varchar(10), primary key (id));
postgres=# create table t2(id int, t1_id uuid, foreign key (t1_id) references t1(id));
postgres=# insert into t1(content) ('a');
postgres=# insert into t1(content) values ('a');
postgres=# insert into t1(content) values ('b');
postgres=# insert into t1(content) values ('c');

我们已经成功地在t1中创建了三个条目。向t2添加一个条目:

postgres=# select * from t1;
                  id                  | content
--------------------------------------+---------
 b6148ae3-db56-4a4a-8d46-d5b4f04277ac | a
 03abd324-8626-4fb1-9cb0-593373abf9ca | b
 9f12b297-3f60-48a7-8282-e27c3aff1152 | c
(3 rows)


postgres=# insert into t2 values(1, '9f12b297-3f60-48a7-8282-e27c3aff1152');

尝试从t1中选择具有t2中未出现的最小ID的行,请注意这失败了。

postgres=# select min(t1.id) from t1 left outer join t2 on t1.id = t2.t1_id where t2.id is null;
 min
-----

(1 row)

在这里,我们可以选择t1中的两个未引用条目,并且可以独立选择最小UUID:

postgres=# select t1.id from t1 left outer join t2 on t1.id = t2.t1_id where t2.id is null;
                  id
--------------------------------------
 03abd324-8626-4fb1-9cb0-593373abf9ca
 b6148ae3-db56-4a4a-8d46-d5b4f04277ac
(2 rows)

postgres=# select min(id) from t1;
                 min
--------------------------------------
 03abd324-8626-4fb1-9cb0-593373abf9ca
(1 row)

所以,当我尝试选择最小UUID同时尝试执行左向外连接时,会发生一些有趣的事情。

编辑:使用“不存在”时存在相同的问题:

postgres=# select min(id) from t1 where not exists (select t1_id from t2 where t2.t1_id = t1.id);
 min
-----

(1 row)

但在使用not in时,问题不会出现:

postgres=# select min(id) from t1 where id not in (select t1_id from t2);
                 min
--------------------------------------
 03abd324-8626-4fb1-9cb0-593373abf9ca
(1 row)

共有1个答案

沃学
2023-03-14

找到了一个解决方案,原来这篇文章中比较UUID的函数是不正确的。这是我写的函数,它可能性能较差,它通过了之前失败的所有情况:

    CREATE FUNCTION min_uuid(uuid, uuid)
    RETURNS uuid AS $$
    BEGIN
        -- if they're both null, return null
        IF $2 IS NULL AND $1 IS NULL THEN
            RETURN NULL ;
        END IF;

        -- if just 1 is null, return the other
        IF $2 IS NULL THEN
            RETURN $1;
        END IF ;
        IF $1 IS NULL THEN
            RETURN $2;
          END IF;

        -- neither are null, return the smaller one
        IF $1 > $2 THEN
            RETURN $2;
        END IF;

        RETURN $1;
    END;
    $$ LANGUAGE plpgsql;


    create aggregate min(uuid) (
      sfunc = min_uuid,
      stype = uuid,
      combinefunc = min_uuid,
      parallel = safe,
      sortop = operator (<)
    );
 类似资料:
  • 我开始学习JPA,并基于我在SQL Server中测试的以下本机SQL实现了一个使用JPA查询的示例: 根据上面的SQL,我构造了以下JPQL查询: 正如您所看到的,我仍然缺少原始查询中的条件。我的问题是,我怎样才能把它放入我的JPQL中?

  • LEFT OUTER JOIN 左外连接 [ ] 需求:查询所有分类,如果该分类下没有商品,则不显示该分类 [ ] 实现: SELECT `goods`.`id`, `goods`.`title`, `goods`.`price`, `goods`.`cate_id`, `cate`.`id`, `cate`, `cate.title` F

  • 问题内容: 我有这些MySQL表: 表格1: 表2: 而这个查询: 此查询将返回table1的所有行,即1,2,3 我只想选择在左关节中找不到的行。所以它应该只返回ID为ID的行 我想要与INNER JOIN相反,它将仅选择在联接中找到的行。如何获得相反的结果(例如是否存在左联接),忽略它并移至下一行。希望我明白 问题答案: 您可以使用以下查询: 虽然,根据您的索引,您可能会发现两个联接的性能更好

  • 我有这些MySQL表: 表1: 表2: 而这个查询: 此查询将返回table1中1,2,3的所有行 我只想选择在左关节中找不到的行。因此,它应该只返回id为 我想要一种与内部联接相反的方式,它将只选择联接中找到的行。如何获得相反的方式,比如如果存在左联接,忽略它并移动到下一行。希望我很清楚

  • 问题内容: 我试图一次从一张桌子上得到2行。上周的最小日期时间(今天-7)和最晚的日期(今天)的一个。 我的桌子: 我可以通过以下方式选择上周的数据: 但我只想要第1行和第125行,因为这些是用于计算的行。所以我的问题是: 如何从上一个查询的结果中选择2行(带有MIN和MAX日期)? 问题答案: 您可以使用此: 编辑: 由于两台计算机完全有可能具有相同的值,因此应更新查询以在子句中也包含过滤器。我

  • MariaDB 用于返回条件中指定的左侧表中的所有行,并仅返回满足连接条件的其他表中的行。 也被称为。 语法: 图形表示如下: 注: 上图中,两个图形的左侧表(table1)和右侧表(table2)中间交叉蓝色部分,以及左侧表(table1)就是连接返回的结果集。 为了方便演示,我们需要创建两个表,并插入一些数据 - 插入数据 - 当前表中的行记录如下 - 当前表中的行记录如下 - 示例1 使用以