当您连接 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】:
通过select
as
将一列重命名为不同的名称,对每个表进行子查询。然后natural join
子查询。这将执行 inner join
using
所有常见/剩余列。 (或者只使用一个子查询和另一个原始表。)
(请注意,如果您的规范是将来加入您现在加入的列,并且更多列可能会添加到一个或两个表中,那么您需要列出当前列 - 例如,在using
。这类似于特定列的select *
与select
。Ideed,在您加入后,您希望如何获得所有当前列或当前连接列?如果您使用构建过程来减少冗余对于select
s,那么您可以在inner join
上使用它。)
【讨论】:
或者简单地说:... FROM A JOIN B USING (name, date, origin, residence, gender, age, height, weight)
@RickJames 这仍然列出了所有其他列。所以它大约是超长的一半,也就是超长。虽然比on
“更好”。
我添加了一种以编程方式将列列表添加到我的答案的方法。以上是关于当您连接 2 个具有相同架构的表并检查除一个以外的所有字段是不是相等时,如何避免在 SQL 中编写冗长的 where 子句?的主要内容,如果未能解决你的问题,请参考以下文章
将数据插入具有主键的表(多列)中,该表具有除主键以外的数据的另一个数据