联合 5 个或更多具有相同结构和主键的表
Union 5 or more Tables with the same structure and primary key
SQL 5.7.37
我正在使用此代码将 2 sql table 合并为第三个 table。但现在我需要做同样的事情,有 5 个或更多 tables.
create table table3 as
select *
from table1
union all
select *
from table2
where not exists (select 1 from table1 where table1.title = table2.title);
如何向此命令添加更多 table?
这是一组示例数据和所需的结果:
请注意 table 有 一些 行与其他 table 完全相同。我不确定这是否重要。
结构:
ID(主键,自增),Title(唯一,索引),DESC,URL
Ex. Table 1
ID, Title, DESC, URL
1 Bob thisisbob bob.com
2 Tom thisistom tom.com
3 Chad thisischad chad.com
Ex. Table 2
ID, Title, DESC, URL
1 Chris thisischris chris.com
2 Chad thisischad chad.com
3 Dough thisisdough doug.com
Ex. Table 3
ID, Title, DESC, URL
1 Morgan thisismorgan morgan.com
2 Jerome thisisjerome jerome.com
3 Mike thisismike mike.com
Ex. Table 4
ID, Title, DESC, URL
1 Chris thisischris chris.com
2 Chad thisischad chad.com
3 Luke thisisluke luke.com
Result:
What I need in Table 5
ID, Title, DESC, URL
1 Bob thisisbob bob.com
2 Tom thisistom tom.com
3 Chad thisischad chad.com
4 Chris thisischris chris.com
5 Dough thisisdough doug.com
6 Morgan thisismorgan morgan.com
7 Jerome thisisjerome jerome.com
8 Mike thisismike mike.com
9 Luke thisisluke luke.com
如何向我的 union sql 命令添加更多 table?
一个想法可能是 postpone 仅在您聚合了所有 table 之后才生成每个唯一值,只要 UNION_ALL
比 UNION
,你会用这种方式执行一次 DISTINCT
操作,而不是五次。
SET @cnt = 0;
SELECT
(@cnt := @cnt + 1) AS rowNumber,
distinct_aggr_tables.*
FROM
(
SELECT DISTINCT * FROM (
SELECT `Title`, `DESC`, `url` FROM Table1
UNION ALL
SELECT `Title`, `DESC`, `url` FROM Table2
UNION ALL
SELECT `Title`, `DESC`, `url` FROM Table3
UNION ALL
SELECT `Title`, `DESC`, `url` FROM Table4
) aggr_tables
) distinct_aggr_tables
这里是对应的fiddle:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=ea1fa1f668e769cc5b1824dcfb9feb40.
这个解决方案对你有用吗?
编辑:如何select除MySQLtable中的一个以外的所有字段用于此任务
有two interesting ways个这样做:
1) 第一种方法将每个 table 复制到 不同的临时 tables,然后使用ALTER
语句删除我们不感兴趣的列,因此将这些 table 与此代码的第一个版本一起使用。
# for each table
CREATE TEMPORARY TABLE temp_Table1 AS
SELECT * FROM Table1;
ALTER TABLE temp_Table1
DROP Id;
2) 第二种方法使用 准备语句 ,它允许您将查询构建为字符串。这可以帮助这个练习,因为我们可能想要在查询中从 INFORMATION_SCHEMA.COLUMNS
table 中检索所有列名,然后删除我们不感兴趣的字段名,因此传递列列表原始查询的名称。
SET @sql = CONCAT(
'CREATE OR REPLACE VIEW AllTables AS ',
'SELECT
ROW_NUMBER() OVER(ORDER BY Title ASC) AS rowNumber,
distinct_aggr_tables.*
FROM
(',
'SELECT DISTINCT
*
FROM
(
SELECT ',
(SELECT CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ')
FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_NAME = 'Table1' AND cols.TABLE_SCHEMA = 'test'),
'FROM
Table1
UNION ALL
SELECT ',
(SELECT CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ')
FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_NAME = 'Table2' AND cols.TABLE_SCHEMA = 'test'),
'FROM
Table2
UNION ALL
SELECT ',
(SELECT CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ')
FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_NAME = 'Table3' AND cols.TABLE_SCHEMA = 'test'),
'FROM
Table3
UNION ALL
SELECT ',
(SELECT CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ')
FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_NAME = 'Table4' AND cols.TABLE_SCHEMA = 'test'),
'FROM
Table4
) aggr_tables
) distinct_aggr_tables;'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
SELECT * FROM AllTables;
请注意,这段代码完全重现了 post 的第一段代码,除了使用 ROW_NUMBER
window 函数而不是自我更新的全局变量。
这个解决方案做了一些假设,根据这些假设应该仔细quick-fixed:
table正好是 4:为了改变这个数量,有必要在每个新的 table 的正确位置复制以下代码:
SELECT ',
(SELECT CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ')
FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_NAME = <new_table_name> AND cols.TABLE_SCHEMA = 'test'),
'FROM
<new_table_name>
当前 table 名称为 Table1
、Table2
、Table3
、Table4
,数据库名称为 test
:当我们查找特定 table 的字段名称时,应替换这些引用(按 table 名称和数据库名称过滤):
SELECT '
(SELECT CONCAT ...
FROM ...
WHERE cols.TABLE_NAME = <table_name> AND cols.TABLE_SCHEMA = <db_name>),
'FROM
<table_name>
要删除的字段名称是'Id',它是所有table的第一列:如果名称不同,则需要更改其名称在删除此列期间。此外,如果这不是第一列,则需要在此处进行一些调整:
# COLUMN_NAME:
# ['Id', 'Title', 'DESC', 'url']
#
# GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'):
# 'Id`,`Title`,`DESC`,`url'
#
# REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', '')
# '`Title`,`DESC`,`url'
#
# CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ')
# '`Title`,`DESC`,`url`'
(加反引号是为了避免DESC
造成的异常)
Note1: 四个SELECT groups for each table的生成可能是自动化的(最下面的一个简单例子this page) 通过循环使用 INFORMATION_SCHEMA.TABLES
中包含的 table 个名称的变量。然而,我不会冒险走那条路,因为使用准备好的语句和来自另一个 table (INFORMATION_SCHEMA.COLUMNS cols
).[= 的计算值的 CONCAT 来处理要评估的字符串文本变得很困难。 34=]
Note2:无法在 sql fiddle 内看到此代码的效果,因为无法访问 INFORMATION_SCHEMA
db tables。该代码已在 MySQL 8.0 数据库上进行了离线测试。
第一种方法可能会占用大量内存,而如果在修复中谨慎处理以定制您的数据库,第二种方法可能会更有效。
总的来说没有完美的解决方案,但有些可能会解决您的问题。
ps:非常欢迎任何建议的改进 post。
SQL 5.7.37
我正在使用此代码将 2 sql table 合并为第三个 table。但现在我需要做同样的事情,有 5 个或更多 tables.
create table table3 as
select *
from table1
union all
select *
from table2
where not exists (select 1 from table1 where table1.title = table2.title);
如何向此命令添加更多 table?
这是一组示例数据和所需的结果:
请注意 table 有 一些 行与其他 table 完全相同。我不确定这是否重要。
结构: ID(主键,自增),Title(唯一,索引),DESC,URL
Ex. Table 1
ID, Title, DESC, URL
1 Bob thisisbob bob.com
2 Tom thisistom tom.com
3 Chad thisischad chad.com
Ex. Table 2
ID, Title, DESC, URL
1 Chris thisischris chris.com
2 Chad thisischad chad.com
3 Dough thisisdough doug.com
Ex. Table 3
ID, Title, DESC, URL
1 Morgan thisismorgan morgan.com
2 Jerome thisisjerome jerome.com
3 Mike thisismike mike.com
Ex. Table 4
ID, Title, DESC, URL
1 Chris thisischris chris.com
2 Chad thisischad chad.com
3 Luke thisisluke luke.com
Result:
What I need in Table 5
ID, Title, DESC, URL
1 Bob thisisbob bob.com
2 Tom thisistom tom.com
3 Chad thisischad chad.com
4 Chris thisischris chris.com
5 Dough thisisdough doug.com
6 Morgan thisismorgan morgan.com
7 Jerome thisisjerome jerome.com
8 Mike thisismike mike.com
9 Luke thisisluke luke.com
如何向我的 union sql 命令添加更多 table?
一个想法可能是 postpone 仅在您聚合了所有 table 之后才生成每个唯一值,只要 UNION_ALL
比 UNION
,你会用这种方式执行一次 DISTINCT
操作,而不是五次。
SET @cnt = 0;
SELECT
(@cnt := @cnt + 1) AS rowNumber,
distinct_aggr_tables.*
FROM
(
SELECT DISTINCT * FROM (
SELECT `Title`, `DESC`, `url` FROM Table1
UNION ALL
SELECT `Title`, `DESC`, `url` FROM Table2
UNION ALL
SELECT `Title`, `DESC`, `url` FROM Table3
UNION ALL
SELECT `Title`, `DESC`, `url` FROM Table4
) aggr_tables
) distinct_aggr_tables
这里是对应的fiddle:https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=ea1fa1f668e769cc5b1824dcfb9feb40.
这个解决方案对你有用吗?
编辑:如何select除MySQLtable中的一个以外的所有字段用于此任务
有two interesting ways个这样做:
1) 第一种方法将每个 table 复制到 不同的临时 tables,然后使用ALTER
语句删除我们不感兴趣的列,因此将这些 table 与此代码的第一个版本一起使用。
# for each table
CREATE TEMPORARY TABLE temp_Table1 AS
SELECT * FROM Table1;
ALTER TABLE temp_Table1
DROP Id;
2) 第二种方法使用 准备语句 ,它允许您将查询构建为字符串。这可以帮助这个练习,因为我们可能想要在查询中从 INFORMATION_SCHEMA.COLUMNS
table 中检索所有列名,然后删除我们不感兴趣的字段名,因此传递列列表原始查询的名称。
SET @sql = CONCAT(
'CREATE OR REPLACE VIEW AllTables AS ',
'SELECT
ROW_NUMBER() OVER(ORDER BY Title ASC) AS rowNumber,
distinct_aggr_tables.*
FROM
(',
'SELECT DISTINCT
*
FROM
(
SELECT ',
(SELECT CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ')
FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_NAME = 'Table1' AND cols.TABLE_SCHEMA = 'test'),
'FROM
Table1
UNION ALL
SELECT ',
(SELECT CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ')
FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_NAME = 'Table2' AND cols.TABLE_SCHEMA = 'test'),
'FROM
Table2
UNION ALL
SELECT ',
(SELECT CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ')
FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_NAME = 'Table3' AND cols.TABLE_SCHEMA = 'test'),
'FROM
Table3
UNION ALL
SELECT ',
(SELECT CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ')
FROM INFORMATION_SCHEMA.COLUMNS cols
WHERE cols.TABLE_NAME = 'Table4' AND cols.TABLE_SCHEMA = 'test'),
'FROM
Table4
) aggr_tables
) distinct_aggr_tables;'
);
PREPARE stmt FROM @sql;
EXECUTE stmt;
SELECT * FROM AllTables;
请注意,这段代码完全重现了 post 的第一段代码,除了使用 ROW_NUMBER
window 函数而不是自我更新的全局变量。
这个解决方案做了一些假设,根据这些假设应该仔细quick-fixed:
table正好是 4:为了改变这个数量,有必要在每个新的 table 的正确位置复制以下代码:
SELECT ', (SELECT CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ') FROM INFORMATION_SCHEMA.COLUMNS cols WHERE cols.TABLE_NAME = <new_table_name> AND cols.TABLE_SCHEMA = 'test'), 'FROM <new_table_name>
当前 table 名称为
Table1
、Table2
、Table3
、Table4
,数据库名称为test
:当我们查找特定 table 的字段名称时,应替换这些引用(按 table 名称和数据库名称过滤):SELECT ' (SELECT CONCAT ... FROM ... WHERE cols.TABLE_NAME = <table_name> AND cols.TABLE_SCHEMA = <db_name>), 'FROM <table_name>
要删除的字段名称是'Id',它是所有table的第一列:如果名称不同,则需要更改其名称在删除此列期间。此外,如果这不是第一列,则需要在此处进行一些调整:
# COLUMN_NAME: # ['Id', 'Title', 'DESC', 'url'] # # GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'): # 'Id`,`Title`,`DESC`,`url' # # REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', '') # '`Title`,`DESC`,`url' # # CONCAT(REPLACE(GROUP_CONCAT(COLUMN_NAME SEPARATOR '`,`'), 'Id`,', ''), '` ') # '`Title`,`DESC`,`url`'
(加反引号是为了避免DESC
造成的异常)
Note1: 四个SELECT groups for each table的生成可能是自动化的(最下面的一个简单例子this page) 通过循环使用 INFORMATION_SCHEMA.TABLES
中包含的 table 个名称的变量。然而,我不会冒险走那条路,因为使用准备好的语句和来自另一个 table (INFORMATION_SCHEMA.COLUMNS cols
).[= 的计算值的 CONCAT 来处理要评估的字符串文本变得很困难。 34=]
Note2:无法在 sql fiddle 内看到此代码的效果,因为无法访问 INFORMATION_SCHEMA
db tables。该代码已在 MySQL 8.0 数据库上进行了离线测试。
第一种方法可能会占用大量内存,而如果在修复中谨慎处理以定制您的数据库,第二种方法可能会更有效。
总的来说没有完美的解决方案,但有些可能会解决您的问题。
ps:非常欢迎任何建议的改进 post。