【问题标题】:SQL EXCEPT: How to identify New Records VS Changed RecordsSQL EXCEPT:如何识别新记录 VS 更改记录
【发布时间】:2014-06-08 05:12:41
【问题描述】:

虽然我的帖子和this类似,但我还是觉得这和那个有点不同。

我有 2 个 CSV 文件。

File A                                       File B
+-------------------------------------------------------------------+
| Name         | Country                     Name         | Country |
+-------------------------------------------------------------------+
| Ferrari      | Italy                       Jaguar       | British |
| Mercedes     | Germany                     Chevrolet    | America |
| Jaguar       | British                     Bugatti      | Italy   |
| Nissan       | Japan                       Tata         | India   |
| Chevrolet    | USA                         Nissan       | Japan   |
+-------------------------------------------------------------------+

以上仅用于说明。一般来说,我在两个文件中都有更多的行和列,但它们的结构是相同的。

我被要求高效地对所有列进行行级比较。因此,我建议使用 HSQLDB 来代替以编程方式进行 CREATE TEXT TABLESET SOURCE 分别与文件,然后在文件之间进行EXCEPT 操作。我做了代码,它就像一个魅力。下面是我为实现相同目的而编写的 SQL 部分。

CREATE TABLE COMPARE_TABLE AS (SELECT SRC.*, 'SRC-TGT' compare_order FROM TABLEA SRC EXCEPT SELECT TGT.*, 'SRC-TGT' compare_order FROM TABLEB TGT) WITH DATA;
INSERT INTO COMPARE_TABLE SELECT TGT.*, 'TGT-SRC' compare_order FROM TABLEB TGT EXCEPT SELECT SRC.*, 'TGT-SRC' compare_order FROM TABLEA SRC;

这给了我一个如下所示的结果表(考虑到上面的示例数据):

比较表

+------------+----------+---------------+
|   Name     | Country  | Compare_order |
+------------+----------+---------------+
| Ferrari    | Italy    | SRC-TGT       |
| Mercedes   | Germany  | SRC-TGT       |
| Chevrolet  | USA      | SRC-TGT       |
| Chevrolet  | America  | TGT-SRC       |
| Bugatti    | Italy    | TGT-SRC       |
| Tata       | India    | TGT-SRC       |
+------------+----------+---------------+

从这里,我需要找出每一行不匹配的原因?至少,从广义上讲,我想将其分为 3 类:

  • 源头上的新功能
  • Target 的新功能
  • 值已更改(如果可能,哪些列?)

最后,我希望我的表格如下所示:

COMPARE_TABLE

+------------+----------+---------------+------------------------+
|   Name     | Country  | Compare_order |     Failure_Reason     |
+------------+----------+---------------+------------------------+
| Ferrari    | Italy    | SRC-TGT       | New at Source          |
| Mercedes   | Germany  | SRC-TGT       | New at Source          |
| Chevrolet  | USA      | SRC-TGT       | Country value mismatch |
| Chevrolet  | America  | TGT-SRC       | Country value mismatch |
| Bugatti    | Italy    | TGT-SRC       | New at Target          |
| Tata       | India    | TGT-SRC       | New at Target          |
+------------+----------+---------------+------------------------+

我该怎么做呢?我们甚至可以在 SQL 中做到这一点吗?

非常感谢任何帮助。

【问题讨论】:

  • 请格式化您的问题
  • 为什么这个问题被标记为mysql
  • @eggyal 我将最终的 COMPARE_TABLE 转储到 mysql。我接下来的步骤也可以在mysql中。这就是为什么。
  • MySQL 不支持except(或intersect)所以你需要在那里找到不同的方法。

标签: mysql sql left-join except


【解决方案1】:

您可以进行基本比较:

select name, country,
       (case when sum(which = 'src') > 0 and sum(which = 'tgt') then 'DROPPED'
             when sum(which = 'src') = 0 and sum(which = 'tgt') then 'NEW'
        end) as OP
from ((select 'src' as which, name, country
       from tableA
      ) union all
      (select 'tgt', name, country
       from tableB
      )
     ) ab
group by name, country;

但这并不能提供逐列比较。这有点困难。让我假设Name 是唯一的,所以它可以用作键。下面进行比较,但每个名称产生一行:

select name,
       (case when src.country is null then dest.country
             when tgt.country is null then tgt.country
             when src.country = tgt.country then dest.country
             else (src.country, '-->', tgt.country)
        end) as country,
       (case when src.country is null then 'new'
             when tgt.country is null then 'dropped'
             when src.country = tgt.country then 'same'
             else 'changed'
        end) as country,
from (select name from TableA union select name from TableB
     ) names left outer join
     TableA src
     on names.name = src.name left outer join
     TableB tgt
     on names.name = tgt.name;

当列中的值发生变化时为每个名称获取多行似乎更困难,尽管这也是可能的。

【讨论】:

  • 当我在 Mysql 中运行第二个查询时,出现错误。错误 1241 (21000):操作数应包含 1 列
  • @user3564168 。 . .这意味着name 在两个表中不是唯一的或主键。您在一个或两个表中有重复的名称。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-07-17
  • 1970-01-01
  • 1970-01-01
  • 2015-10-30
相关资源
最近更新 更多