sql—如何将具有不同模式的表合并到一个超集表中?

5lhxktic  于 2021-07-24  发布在  Java
关注(0)|答案(3)|浏览(385)

我不确定“超集”是否是描述我在这里要做的事情的最准确的方式,但我有两个类似的表格:
表a: a | b | c | f | h | j | o | q 表b: c | a | d | f | g | h | i | j | p | q 我要做的是将它们合并到一个表中,该表包含两个表中的所有记录,每一行的原始列中都有数据,包括两个表中所有不同的列,如下所示:
合并表: a | b | c | d | f | g | h | i | j | o | p | q 我并不特别在意顺序,因为我正在尝试将暂存表合并在一起。他们 c 以及 a 列可能会在最后一个表中失败-这对我来说无关紧要。
这意味着某些列将不包含表的一半的任何数据,但这就是我的想法-我不想丢失任何信息,并且不是所有的表都有一个兼容的模式。如果两个列名相同,则它们是相同的逻辑列,并且在新表中不应该有两个(我将手动确保逻辑上相同的列的名称相同)。
我一直在用 INSERT INTO new SELECT * FROM old1 UNION ALL SELECT * FROM old2 但这在这里行不通,忘了 UNION ,这仅在模式匹配时有效。在这种情况下,新表将有一个结合了旧模式的模式。这个 MERGE 命令似乎也有类似的问题,需要一些兼容的模式。
有没有办法自动完成?每一个表都有将近70列,顺序不一致,我要做一打这样的合并,所以我尝试用sql自动重构。
使用 NATURAL JOIN 但这似乎行不通——例如,表a:
a | b | c 1 | 5 | 35 表b: b | d | f 5 | 66 | 34 NATURAL JOIN 产量:
a | b | c | d | f 1 | 5 | 35| 66| 34 我想要的不是自然连接,只是没有重复列的纯连接: a | b | c | d | f 1 | 5 | 35| | | 5 | | 66|34

yhqotfr8

yhqotfr81#

哎呀,这可不容易。生成联合查询或自定义自定义自定义项。在access中,我将使用vba构建查询对象或将数据写入表。即使使用vba,也需要定义字段对的“Map”表。所以,如果mariadb有相似的功能,就应用相同的概念。
将此视为工会:

SELECT "A" AS Src, a, b, c, Null AS d, f, Null AS g, h, Null AS i, j, o, Null AS p, q FROM TableA
UNION 
SELECT "B", a, Null, c, d, f, g, h, i, j, Null, p, q FROM TableB;
agxfikkp

agxfikkp2#

即使表是不同的列计数,它们仍然可以按如下方式并集:

SELECT a, b, c, NULL AS d, f, NULL AS g, h, NULL AS i, j, o, NULL AS p, q
FROM tbl1
UNION ALL
SELECT a, NULL AS b, c, d, f, g, h, i, j, NULL AS o, p, q
FROM tbl2;

遗憾的是,在mysql/mariadb中,如果不显式地键入所有列名并手动定位它们,就无法做到这一点。
sas proc sql支持您所需要的外部union corr操作符。解决方案如下:

SELECT * FROM tbl1
OUTER UNION CORR
SELECT * FROM tbl2;

不幸的是,它在mysql/mariadb中还不可用。您最终可能会模拟类似的情况,使用group\u concat和concat、ifnull和其他函数,通过使用information\u schema.columns生成select query as prepared语句。。。但我个人不会这么做。
无论如何-作为这个坏主意的基本出发点。。。以下查询将列出两个表中的所有唯一列(如果数据库为“test”,表为“tbl1”和“tbl2”):

SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'tbl1'
UNION
SELECT COLUMN_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'tbl2'
ORDER BY COLUMN_NAME;

现在我们将它们合并到一个用逗号分隔的字段中:

SELECT GROUP_CONCAT(CONCAT("NULL AS ", COLUMN_NAME)) AS columns
FROM (  SELECT COLUMN_NAME
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'tbl1'
        UNION
        SELECT COLUMN_NAME
        FROM INFORMATION_SCHEMA.COLUMNS
        WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'tbl2'
        ORDER BY COLUMN_NAME
) AS grouped_columns;

然后我们可以通过准备好的select语句运行这个“命令”,在本例中,该语句将打印具有空值的起始行:

SET @s:='';
SELECT @s:=CONCAT('SELECT ', columns) AS start_row
            FROM
            (
                SELECT GROUP_CONCAT(CONCAT('NULL AS ',COLUMN_NAME)) AS columns
                FROM (  SELECT COLUMN_NAME
                        FROM INFORMATION_SCHEMA.COLUMNS
                        WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'tbl1'
                        UNION
                        SELECT COLUMN_NAME
                        FROM INFORMATION_SCHEMA.COLUMNS
                        WHERE TABLE_SCHEMA = 'test' AND TABLE_NAME = 'tbl2'
                        ORDER BY COLUMN_NAME
                ) AS grouped_columns
            ) AS grouped_columns;
PREPARE stmt FROM @s;
EXECUTE stmt;

这个“怪物”查询将产生类似钩子行的内容。。。

+------+------+------+------+------+------+------+------+------+------+------+------+
| a    | b    | c    | d    | f    | g    | h    | i    | j    | o    | p    | q    |
+------+------+------+------+------+------+------+------+------+------+------+------+
| NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL |
+------+------+------+------+------+------+------+------+------+------+------+------+

在这种情况下,您必须弄清楚如何将tbl1和tbl2中的条目添加到各自的位置上。所以。。。祝你好运。我不会挣扎着去做:)它已经非常低效了,我甚至还没有接近解决方案。这是做你想做的事的禁区。只需手动键入列名。

rlcwz9us

rlcwz9us3#

基本上,你似乎想要 full join 以及 using :

select *
from a full join
     b
     using (a, c, f, j, h, i, j, p, q)

mariadb不支持,但你可以:

select *
from a left join
     b
     using (a, c, f, j, h, i, j, p, q)
union all
select *
from a right join
     b
     using (a, c, f, j, h, i, j, p, q)
where a.a is null;

相关问题