我想找到具有相同ID和指示器但具有不同值的记录.以下是我的样本数据.

declare @table1 table (id int, indicator varchar(20),value int);
INSERT INTO @table1 VALUES
(11,'AC',80),
(11,'HE',90),
(12,'AC',10),
(12,'HE',80),
(13,'AC',10),
(13,'HE',10);


declare @table2 table(id int, indicator varchar(20),value int);
INSERT INTO @table2 VALUES
(11,'AC',80),
(11,'HE',90),
(12,'AC',11),
(12,'HE',80),
(13,'AC',10),
(14,'AC',10);

我创造了db<>fiddle

根据上面的样本数据,将有4个场景:

1.11两个表中都存在,每个ID都有相同的指标和值,所以我不会登录记录.

2.带有指标‘AC’的12与表2(10和11)的值不同,这是我需要的记录.

3.13在两个表中都存在,但表%1有2条记录,两个指标‘AC’具有相同的值.在本例中,我只需要表2中没有匹配记录的那个.(在本例中,ITS(13,‘HE’,10). 请注意,表2中也可能出现同样的情况.因此,表1的结果将变为空,并列出表2中的结果

4.我只存在于其中一张表中,例如:14.那么我就不需要这张了.

换句话说,我需要的记录,如果2表有相同的ID和指标,但与不同的值.如果两个表具有相同ID,但具有不同的指示符和值,我也需要记录此记录.

因此,我确实希望我的结果是这样的.

Table 1 ID Table 1 Indicator Table 1 Value Table 2 ID Table 2 Indicator Table 2 Value
12 AC 10 12 AC 11
13 HE 10 NULL NULL NULL

推荐答案

这是XOR连接的一个变体:您需要对两边求和FULL JOIN,但只有在有差异的情况下才取结果.这里的调整是,如果ID不存在于一侧,那么您还希望忽略这些行(类似于INNER JOIN).

我能想到的最好的办法是结合使用FULL JOIN和双方的条件窗口式计数

SELECT *
FROM (
    SELECT
      Table1ID = t1.id,
      Table1Indicator = t1.indicator,
      Table1Value = t1.value,
      Table2ID = t2.id,
      Table2Indicator = t2.indicator,
      Table2Value = t2.value,
      count1 = CASE WHEN t1.id IS NOT NULL THEN COUNT(t2.id) OVER (PARTITION BY t1.id) END,
      count2 = CASE WHEN t2.id IS NOT NULL THEN COUNT(t1.id) OVER (PARTITION BY t2.id) END
    FROM @table1 t1
    FULL JOIN @table2 t2
      ON t2.id = t1.id
     AND t2.indicator = t1.indicator
) t
WHERE (Table1Value <> Table2Value)
   OR (Table1Value IS NULL AND count2 > 0)
   OR (Table2Value IS NULL AND count1 > 0);

db<>fiddle

请注意,小提琴也适用于表2中(13,'LE',10)的额外情况.

这里的逻辑如下:

  • 首先将所有内容完全连接在一起,这将使我们从两边获得所有行,但匹配的是idindicator.
  • 窗口计数的计算依据:按id1分组,计算id2的匹配数,反之亦然.不计算任何空组的计数.
  • 然后按如下方式过滤:
    • 如果这两个value不同(但都不为空),则我们有匹配项,因此将其包括在内.
    • 如果一侧为空,但另一侧存在id,则包含.
    • 反之亦然

Sql相关问答推荐

创建每小时重置的序列号

如何根据给定条件PostgreSQL迭代减少组中的行数

Ffltter&;Dart SQL Lite包:是否可以在一个查询中执行多条更新语句(每次执行不同的WHERE参数)

检索上一个星期四和上一个星期三

如何隐藏聚合JSON数组元素的键

动态组/转置

在Athena中使用regexp提取括号前的字符串值

从单个表达式中的分隔字符串中取平均值

VS代码无法识别SQL代码中带括号的字符串

聚合内部的条件在哪里?

获取主表条目,其中最新的辅助条目是 6 个月前

GRAFANA 数据库查询错误:pq:列名称不存在

DbUp for sqlserver 在 dbo 授权下为非 dbo 用户创建架构

在没有订单的情况下,如何生成一个值为0的顾客天数行

我如何编写一个遍历数组数组并将所有值连接成一个字符串的 postgres 函数

字符串从更改到表列和查询中的一行的转换错误

如何通过子 Select 在一次更新(并行数组)中多次更新相同的行

为什么 Oracle 在一个查询中对同一张表同时执行 TABLE SCAN 和 INDEX UNIQUE SCAN?

当没有任何行存在时,将一个表中的行插入到另一个表中的更好方法

查找距上一条记录大于或等于 30 天的记录