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

如何在唯一索引中合并两个可能为空值的表?

陈嘉荣
2023-03-14

如何将(upsert和delete孤立行)合并到tablea

:

+---------+--------+----------+-------+
| company | option | category | rates |
+---------+--------+----------+-------+
| a       | f      | null     | 2.5   |
+---------+--------+----------+-------+
| a       | f      | d        | 2     | *
+---------+--------+----------+-------+
| a       | g      | e        | 3     | **
+---------+--------+----------+-------+
| c       | g      | e        | 4     |
+---------+--------+----------+-------+
| d       | f      | d        | 1     |
+---------+--------+----------+-------+
+---------+--------+----------+-------+
| company | option | category | rates |
+---------+--------+----------+-------+
| a       | f      | null     | 2.5   |
+---------+--------+----------+-------+
| a       | g      | e        | 4     |
+---------+--------+----------+-------+
| c       | g      | e        | 4     |
+---------+--------+----------+-------+
+---------+--------+----------+-------+
| company | option | category | rates |
+---------+--------+----------+-------+
| a       | f      | null     | 2.5   |
+---------+--------+----------+-------+
| a       | g      | e        | 4     | <-
+---------+--------+----------+-------+
| c       | g      | e        | 4     |
+---------+--------+----------+-------+
| d       | f      | d        | 1     |
+---------+--------+----------+-------+

这里有一把小提琴:https://rextester.com/quvc30763

我想先用下面的代码删除孤立行:

DELETE from tableA
 USING tableB
 WHERE 
   -- ignore rows with IDs that don't exist in tableB
   tableA.company = tableB.company
   -- ignore rows that have an exact all-column match in tableB
   AND NOT EXISTS 
      (select * from tableB 
      where tableB.company is not distinct from tableA.company 
      AND tableB.option is not distinct from tableA.option 
      AND tableB.category is not distinct from tableA.category );

然后用这个Ussert:

 INSERT INTO tableA (company, option, category, rates) 
   SELECT company, option, category, rates
   FROM   tableB
 ON CONFLICT (company, option, category) 
 DO update
   set rates= EXCLUDED.rates
 WHERE 
      tableA.rates IS DISTINCT FROM 
      EXCLUDED.rates;
    null

共有1个答案

丁阳炎
2023-03-14

我认为你走在正确的道路上。但是nullunique存在设计问题:

选项类别可以为null。在这些情况下,null被认为是相等的。您当前的唯一索引不认为null值相等,因此不强制执行您的要求。这甚至在开始合并之前就会产生歧义。null值对您试图实现的内容没有好处。解决这个问题会产生更多的工作和更多的失败点。考虑使用一个特殊的值而不是null,一切都就绪了。您正在考虑-1。任何对实际数据类型和属性性质自然有意义的内容。

也就是说,delete还有一个额外的隐藏的问题:它将尝试删除孤立行的次数与tablebcompany上的匹配次数一样多。没有什么会失败,因为过度的尝试什么也不做,但它不必要的昂贵。改为使用exists两次:

DELETE FROM tableA a
WHERE  EXISTS (
   SELECT FROM tableB b
   WHERE a.company = b.company
   )
AND    NOT EXISTS (
   SELECT FROM tableB b
   WHERE (a.company, a.option, a.category) IS NOT DISTINCT FROM
         (b.company, b.option, b.category)
   );

并确保没有对表的并发写操作,否则您可能会面临竞争条件和/或死锁,除非您做更多...

 类似资料:
  • 问题内容: 自几个月前以来,我的集群每天都有一个索引,每个索引有5个分片(默认),并且由于分片太多(超过1000个),我无法在整个集群上运行查询。 文档ID是自动生成的。 如何将索引合并为一个索引,处理有冲突的ID(甚至可能发生冲突)并更改类型? 我正在使用ES版本5.2.1 问题答案: 仅在使用ELK堆栈几个月并逐日创建索引后才可见的常见问题。这里有一些选项可以解决性能问题。 首先,您可以用来限

  • 问题内容: 这是具有3列(ID,UNIQUE_VALUE,UNIQUE_GROUP_ID)的示例表 我希望下面的记录可以被允许: 或者 或( 注:这种情况是不允许的,也不) 并且这些是不允许的: 我在最后2列上创建了唯一索引,但是仅允许前2个示例。 仅当两者都不为null时,才可以让db检查这两列的唯一性吗? 问题答案: 您只想对和都不为空的行实施唯一性。为此,您可以使用基于函数的唯一索引:

  • 问题内容: 我有以下两个表,您也可以在此处的SQL提琴中找到它们: 我从这里使用VBA 合并两个表: 所有这些完美地工作。 但是,现在我希望日期显示为唯一。 结果应如下所示: 我需要在代码中进行哪些更改才能使其正常工作? 问题答案: 使用和:

  • 在MongoDB3.2中有可能避免这种情况吗?

  • 我必须确保两个值是否为非空值。当first和second具有非空值时,将first作为参数传递给second。如果其中一个为空值,则返回false。这可以在下面的一段代码中完成: 也可以用简短的形式完成: 我想知道如何用可选的流利的形式来做这件事。

  • 问题内容: 我正在尝试在表中的两个字段上创建唯一约束。但是,很可能一个人将为空。我只要求如果它们都不为null(永远不会为null),则它们必须是唯一的。 忽略表和字段名称的语义以及这是否有意义-我刚刚做了一些补充。 有没有一种方法可以在这些字段上创建唯一约束,从而对两个非null值强制执行唯一性,但是如果有多个条目(非null和null),则可以忽略呢? 这个问题是针对SQL Server的,我