【问题标题】:mariadb complex combine table columns based on common columns and add new column when not found in common columns on outputmariadb complex 基于公共列组合表列,并在输出的公共列中找不到时添加新列
【发布时间】:2021-07-02 18:11:07
【问题描述】:

我有 3 个如下表。其中 id, fcd, ref 列在表中是通用的,我正在尝试将所有表列合并到单个表中。

MariaDB [test]> select * from t1;
+----+-----+-----+------+------+
| id | fcd | ref | c1   | c2   |
+----+-----+-----+------+------+
|  1 |   1 | 1.0 | 0.10 | 2.00 |
|  1 |   2 | 1.5 | 0.40 | 2.22 |
|  3 |   1 | 2.0 | 0.10 | 4.30 |
|  3 |   2 | 3.2 | 0.01 | 6.60 |
|  5 |   3 | 7.5 | 0.00 | 7.70 |
+----+-----+-----+------+------+
5 rows in set (0.001 sec)

MariaDB [test]> select * from t2;
+----+-----+------+------+------+
| id | fcd | ref  | c3   | c4   |
+----+-----+------+------+------+
|  1 |   1 | 1.00 | 0.06 | 0.76 |
|  1 |   2 | 1.20 | 0.32 | 0.87 |
|  5 |   2 | 6.50 | 0.44 | 0.09 |
|  5 |   3 | 6.68 | 0.47 | 0.08 |
+----+-----+------+------+------+
4 rows in set (0.001 sec)

MariaDB [test]> select * from t3;
+----+-----+-----+------+------+
| id | fcd | ref | c5   | c6   |
+----+-----+-----+------+------+
|  1 |   3 | 1.1 | 0.02 | 0.12 |
|  1 |   4 | 2.0 | 0.23 | 0.11 |
|  7 |   1 | 3.2 | 0.45 | 0.43 |
|  7 |   2 | 7.5 | 0.54 | 0.67 |
+----+-----+-----+------+------+
4 rows in set (0.000 sec)

这是我尝试使用联合没有运气

MariaDB [test]> select id,fcd,ref,c1,c2,null c3, null c4, null c5, null c6 from t1  union all  select id,fcd,ref,null c1, null c2, c3, c4,null c5, null c6 from t2 union all select id,fcd,ref,null c1, null c2, null c3, null c4,c5, c6 from t3 order by id, fcd, ref;
+----+-----+------+------+------+------+------+------+------+
| id | fcd | ref  | c1   | c2   | c3   | c4   | c5   | c6   |
+----+-----+------+------+------+------+------+------+------+
|  1 |   1 | 1.00 | NULL | NULL | 0.06 | 0.76 | NULL | NULL |
|  1 |   1 | 1.00 | 0.10 | 2.00 | NULL | NULL | NULL | NULL |
|  1 |   2 | 1.20 | NULL | NULL | 0.32 | 0.87 | NULL | NULL |
|  1 |   2 | 1.50 | 0.40 | 2.22 | NULL | NULL | NULL | NULL |
|  1 |   3 | 1.10 | NULL | NULL | NULL | NULL | 0.02 | 0.12 |
|  1 |   4 | 2.00 | NULL | NULL | NULL | NULL | 0.23 | 0.11 |
|  3 |   1 | 2.00 | 0.10 | 4.30 | NULL | NULL | NULL | NULL |
|  3 |   2 | 3.20 | 0.01 | 6.60 | NULL | NULL | NULL | NULL |
|  5 |   2 | 6.50 | NULL | NULL | 0.44 | 0.09 | NULL | NULL |
|  5 |   3 | 6.68 | NULL | NULL | 0.47 | 0.08 | NULL | NULL |
|  5 |   3 | 7.50 | 0.00 | 7.70 | NULL | NULL | NULL | NULL |
|  7 |   1 | 3.20 | NULL | NULL | NULL | NULL | 0.45 | 0.43 |
|  7 |   2 | 7.50 | NULL | NULL | NULL | NULL | 0.54 | 0.67 |
+----+-----+------+------+------+------+------+------+------+
13 rows in set (0.001 sec)

如您所见1 | 1 | 1 存在重复,以上一个没有正确组合

这是我所期望的

| id    | fcd   | ref   | c1    | c2    | c3    | c4    | c5    | c6    |
|----   |-----  |------ |------ |------ |------ |------ |------ |------ |
| 1     | 1     | 1     | 0.1   | 2     | 0.06  | 0.76  | NULL  | NULL  |
| 1     | 2     | 1.2   | NULL  | NULL  | 0.32  | 0.87  | NULL  | NULL  |
| 1     | 2     | 1.5   | 0.4   | 2.22  | NULL  | NULL  | NULL  | NULL  |
| 1     | 3     | 1.1   | NULL  | NULL  | NULL  | NULL  | 0.02  | 0.12  |
| 1     | 4     | 2     | NULL  | NULL  | NULL  | NULL  | 0.23  | 0.11  |
| 3     | 1     | 2     | 0.1   | 4.3   | NULL  | NULL  | NULL  | NULL  |
| 3     | 2     | 3.2   | 0.01  | 6.6   | NULL  | NULL  | NULL  | NULL  |
| 5     | 2     | 6.5   | NULL  | NULL  | 0.44  | 0.09  | NULL  | NULL  |
| 5     | 3     | 6.68  | NULL  | NULL  | 0.47  | 0.08  | NULL  | NULL  |
| 5     | 3     | 7.5   | 0     | 7.7   | NULL  | NULL  | NULL  | NULL  |
| 7     | 1     | 3.2   | NULL  | NULL  | NULL  | NULL  | 0.45  | 0.43  |
| 7     | 2     | 7.5   | NULL  | NULL  | NULL  | NULL  | 0.54  | 0.67  |

请高人帮帮我,不知道怎么解决

【问题讨论】:

    标签: mysql mariadb union


    【解决方案1】:

    您可以group by id,fcd,ref对您的查询结果进行汇总:

    select id,fcd,ref,max(c1) c1,max(c2) c2,max(c3) c3,max(c4) c4,max(c5) c5,max(c6) c6 
    from (  
      select id,fcd,ref,c1,c2,null c3, null c4, null c5, null c6 from t1  
      union all  
      select id,fcd,ref,null c1, null c2, c3, c4,null c5, null c6 from t2 
      union all 
      select id,fcd,ref,null c1, null c2, null c3, null c4,c5, c6 from t3 
    ) t
    group by id,fcd,ref
    order by id,fcd,ref;
    

    请参阅demo

    【讨论】:

    • 您的解决方案也很好用,非常感谢,我选择了其他解决方案,因为它没有明确指定 null。
    • @Helen 我很惊讶您更喜欢使用 UNION 的解决方案,它的性能低于 UNION ALL 和 3 LEFT joins。
    • 我真的没有得到更有效的方法,如果我在 id,fcd,ref 上创建唯一索引,您的解决方案只需很少的工作即可产生结果,但会给我一些警告,请指导我哪个更有效在大桌子上时高效
    • 所有 3 个表上的索引均为 create unique index myind on t1 (id,fcd,ref); create unique index myind on t2 (id,fcd,ref); create unique index myind on t3 (id,fcd,ref); explain extended 我不明白为什么会出现此警告
    • @Helen 警告不是错误:dev.mysql.com/doc/refman/8.0/en/explain-extended.html 另外,测试两个查询并决定性能、维护和可扩展性。
    【解决方案2】:

    通过在 idfcdref 列上使用 UNION 而不是 UNION ALL,您可以获得相同的结果:

    SELECT t.id,
           t.fcd,
           t.ref,
           t1.c1,
           t1.c2,
           t2.c3,
           t2.c4,
           t3.c5,
           t3.c6
    FROM
      (SELECT id,
              fcd,
              ref
       FROM t1
       UNION SELECT id,
                    fcd,
                    ref
       FROM t2
       UNION SELECT id,
                    fcd,
                    ref
       FROM t3) AS t
    LEFT JOIN t1 USING(id,
                       fcd,
                       ref)
    LEFT JOIN t2 USING(id,
                       fcd,
                       ref)
    LEFT JOIN t3 USING(id,
                       fcd,
                       ref)
    ORDER BY id,
             fcd,
             ref;
    

    ref:fiddle(感谢@forpas 提供基础数据)

    【讨论】:

    • 这行得通,你能解释一下左连接部分吗?我确实添加了基础数据,但不知道它为什么迁移
    • 您通过删除null as c1 等简化了查询,谢谢
    • 左连接的结果是当行不匹配时,字段返回为null。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-28
    相关资源
    最近更新 更多