当您连接 2 个具有相同架构的表并检查除一个以外的所有字段是不是相等时,如何避免在 SQL 中编写冗长的 where 子句?

Posted

技术标签:

【中文标题】当您连接 2 个具有相同架构的表并检查除一个以外的所有字段是不是相等时,如何避免在 SQL 中编写冗长的 where 子句?【英文标题】:How to avoid writing lengthy where clauses in SQL when you join 2 tables with identical schema and check for equality on all fields but one?当您连接 2 个具有相同架构的表并检查除一个以外的所有字段是否相等时,如何避免在 SQL 中编写冗长的 where 子句? 【发布时间】:2019-04-13 13:49:27 【问题描述】:

如果不用在 where 子句中编写大量由 AND 连接的条件,您是否可以在 SQL 中内部连接 ​​2 个具有相同架构的表,以便 where 子句检查两个表之间每个字段的相等性,但只有一个字段?如果有很多字段(例如,200 个字段),SQL 语句就会变得太长。我正在使用 MariaDB。

例如,假设我有以下内容,其中 'id' 是主键:

TABLE_A(身份证、姓名、日期、出身、居住地、性别、年龄、身高、体重)

TABLE_B(身份证、姓名、日期、出身、居住地、性别、年龄、身高、体重)

当我inner join TABLE_A和TABLE_B时,为了得到除了id之外的所有字段,TABLE_A中的值和TABLE_B中的对应值都相同的所有行,我只能想到做以下事情:

SELECT * FROM TABLE_A INNER JOIN TABLE_B WHERE 
    TABLE_A.name = TABLE_B.name AND 
    TABLE_A.date = TABLE_B.date AND 
    TABLE_A.origin = TABLE_B.origin AND 
    TABLE_A.residence = TABLE_B.residence AND 
    TABLE_A.gender = TABLE_B.gender AND 
    TABLE_A.age = TABLE_B.age AND 
    TABLE_A.height = TABLE_B.height AND 
    TABLE_A.weight = TABLE_B.weight;

有没有更好的方法,不需要写超长的 WHERE 子句?

【问题讨论】:

使用on 而不是WHERE 没有。不是真的。 @D-Shih 哈哈,我刚刚开了个玩笑。 @Strawberry 看我的回答。 【参考方案1】:

如果您告诉我们真正的目标是什么,我们或许能够想出一个解决方案来避免这种混乱的WHERE。同时,这里有一些相关的查询:

这将对行集进行去重:

        ( SELECT * FROM TableA )
        UNION DISTINCT
        ( SELECT * FROM TableB )

这样也行:

SELECT DISTINCT *
    FROM
    (
        ( SELECT * FROM TableA )
        UNION ALL
        ( SELECT * FROM TableB )
    )

这是另一种思考方式。仍然需要大量输入,但您可以复制和粘贴来完成一些工作:

SELECT ...
    FROM TableA
    JOIN TableB
      ON CONCAT_WS("\t", a.name, a.date, ... ) =
         CONCAT_WS("\t", b.name, b.date, ... )

如何在不输入的情况下获取列列表:

SET group_concat_len = 12345;  -- something big enough = 12345;
SELECT  GROUP_CONCAT(column_name)
    FROM  information_schema.columns
    WHERE  table_schema = '...'    -- use the database name
      AND  table_name = 'Table_A'
      AND  column_name != 'id';    -- to exclude `id`

【讨论】:

我添加了一种以编程方式获取列列表的方法。 DISTINCT * 是矛盾的。如果不是,则 OP 有更大的问题!【参考方案2】:

通过selectas 将一列重命名为不同的名称,对每个表进行子查询。然后natural join 子查询。这将执行 inner join using 所有常见/剩余列。 (或者只使用一个子查询和另一个原始表。)

(请注意,如果您的规范是将来加入您现在加入的列,并且更多列可能会添加到一个或两个表中,那么您需要列出当前列 - 例如,在using。这类似于特定列的select *select。Ideed,在您加入后,您希望如何获得所有当前列或当前连接列?如果您使用构建过程来减少冗余对于selects,那么您可以在inner join 上使用它。)

【讨论】:

或者简单地说:... FROM A JOIN B USING (name, date, origin, residence, gender, age, height, weight) @RickJames 这仍然列出了所有其他列。所以它大约是超长的一半,也就是超长。虽然比on“更好”。 我添加了一种以编程方式将列列表添加到我的答案的方法。

以上是关于当您连接 2 个具有相同架构的表并检查除一个以外的所有字段是不是相等时,如何避免在 SQL 中编写冗长的 where 子句?的主要内容,如果未能解决你的问题,请参考以下文章

将数据插入具有主键的表(多列)中,该表具有除主键以外的数据的另一个数据

选择一个表并连接 2 个不同的表

数据步骤/SQL 连接/合并/联合 2 数据集/表并删除相同的行/观察

内连接2个具有相同列名的表

连接两个具有相同键但不同字段的表

如何基于 ManyToManyField 内部连接表并按参数分组并在 Django 中获取最新的表?