【问题标题】:How To Left Join 2 Tables On 2 Different Databases?如何左连接 2 个不同数据库上的 2 个表?
【发布时间】:2012-10-02 05:56:00
【问题描述】:

我有第一个数据库 (dbA) 有这样的表,命名为 Username

+------------------+--------------+
| Username         | PhoneNumber  |
+------------------+--------------+
| jamesbond007     | 555-0074     |
| batmanbegins     | 555-0392     |
+------------------+--------------+

然后,另一方面,我有 dbB 和这样的表,名为 PrivateMessage

+------------------+---------------------------------+
| Username         | Message                         |
+------------------+---------------------------------+
| jamesbond007     | I need new bond-girl            |
| batmanbegins     | thanks for the paycheck, Nolan  |
+------------------+---------------------------------+

现在,如何组合来自 2 个不同数据库的这两个表,以便输出如下所示:

+------------------+--------------+---------------------------------+
| Username         | PhoneNumber  | Message                         |
+------------------+--------------+---------------------------------+
| jamesbond007     | 555-0074     | I need new bond-girl            |
| batmanbegins     | 555-0392     | thanks for the paycheck, Nolan  |
+------------------+--------------+---------------------------------+

【问题讨论】:

  • 由于您有不同的排序规则,请参阅下面的答案。
  • dbA, dbB 是表而不是数据库。

标签: mysql sql


【解决方案1】:

您可以简单地连接不同数据库的表。您需要在 FROM 子句中指定数据库名称。为了让它更短,在上面添加一个ALIAS

SELECT  a.*,          -- this will display all columns of dba.`UserName`
      b.`Message`
FROM  dba.`UserName` a  -- or LEFT JOIN to show all rows whether it exists or not
      INNER JOIN dbB.`PrivateMessage` b    
         ON a.`username` = b.`username`

但在某些情况下,username 中可能没有消息。在这种情况下,如果您仍想显示dba.Username 的所有记录,请使用LEFT JOIN

从您的 cmets 读取,这些表有不同的collation。解决此问题的方法是在您的连接语句中指定COLLATE

SELECT  a.*,          -- this will display all columns of dba.`UserName`
      b.`Message`
FROM  dba.`UserName` COLLATE latin1_swedish_ci a  
      LEFT JOIN dbB.`PrivateMessage` COLLATE latin1_swedish_ci b    
         ON a.`username` = b.`username`

您可以将latin1_swedish_ci 更改为您想要的任何内容。

有关 COLLATION 的更多信息,请参阅此完整列表

Character Sets and Collations in MySQL


如果您有足够的权限ALTER 表,只需使用此语法手动转换和匹配它们的排序规则,

ALTER TABLE tbl_name CONVERT TO CHARACTER SET latin2 COLLATE 'latin2_general_ci';

【讨论】:

  • 上面的答案是连接同一个数据库中的表。您不能轻易地连接来自不同数据库的两个表
  • @fearis 不,上面的答案是连接来自两个不同数据库的两个表:dba.UserNamedbB.PrivateMessagedbadbB 是数据库,UserNamePrivateMessage 是两个表(顺便说一下,来自不同的数据库)。但是,上面的答案仅适用于同一服务器上的数据库
【解决方案2】:

与普通表相同,除了指定数据库:

SELECT dbA.Username, dbA.PhoneNumber, dbB.Message
   FROM dbA.Username LEFT JOIN dbB.PrivateMessage
   ON (dbA.UserName.Username = dbB.PrivateMessage.Username);

注意事项:

  • LEFT JOIN 将返回所有用户,包括没有消息的用户(使用INNER JOIN 仅检索消息的用户)
  • 拥有多条消息的用户会出现多次(使用聚合和GROUP BY 仅检索每个用户的一条消息 - 您必须提供一个标准来选择一条消息)
  • 您需要对两个数据库都有查询权限(否则某些同时拥有这两个数据库权限的用户必须定期在 crontab 中将一个表或表的子集从一个数据库复制到另一个数据库)
  • 排序规则可能不匹配。如果是这种情况,您必须使用COLLATE 更改两个表之一的排序规则,或者使用CONVERT 将一个数据库的字段转换为另一个数据库的字符集: CONVERT(db.table.field USING Latin1) , 这将阻止使用索引从而降低性能。您可以修改这两个表中的一个,但验证您没有中断任何查询或应用程序正在使用 ALTER'ed 表(在紧要关头,将整个数据库转换为正常的UTF8)。
  • 文本字段上的JOINs 效率不是很高,即使您在两个表中都有 INDEX;最好让 Message 表保存一个唯一的数字 userid 来引用消息所有者。我了解具有不同逻辑的两个不同数据库可能不利于此解决方案,但您可以应用上述“技巧”之一(“复制表或其子集”)并定期导出,从数据库到另一个转换和 ID 的表。一个定期查询会很昂贵,但所有后续的 JOIN 都会受益匪浅。

试运行

这会在两个不同的数据库中创建两个具有相同结构的表,并在 第三个​​ 数据库中连接它们。

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.30 openSUSE package

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> CREATE DATABASE first_database;
Query OK, 1 row affected (0.01 sec)

mysql> CREATE DATABASE second_database;
Query OK, 1 row affected (0.00 sec)

mysql> USE first_database;
Database changed
mysql> CREATE TABLE mytable ( x integer, t varchar(32) );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO mytable ( x, t ) VALUES ( 1, 'One in First Database' ), ( 2, 'Two in First Database' );
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> USE second_database;
Database changed
mysql> CREATE TABLE mytable ( x integer, t varchar(32) );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO mytable ( x, t ) VALUES ( 1, 'One in Second Database' ), ( 3, 'Three in Second Database' );
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> USE test;
Database changed
mysql> SELECT * FROM first_database.mytable LEFT JOIN second_database.mytable USING ( x );
+------+-----------------------+------------------------+
| x    | t                     | t                      |
+------+-----------------------+------------------------+
|    1 | One in First Database | One in Second Database |
|    2 | Two in First Database | NULL                   |
+------+-----------------------+------------------------+
2 rows in set (0.00 sec)

mysql>

【讨论】:

  • 我收到此错误消息:#1267 - 排序规则 (utf8_unicode_ci,IMPLICIT) 和 (utf8_general_ci,IMPLICIT) 用于操作 '=' 的非法混合
  • 我遇到了与@Robert Hanson 相同的错误。 @Robert 你知道了吗?
  • 这将连接同一个数据库中的两个表
  • 不,@fearis - 它将 dbA 中的表连接到 dbB 中的表,dbA 和 dbB 是两个不同的数据库。如果您尝试了此操作但没有成功,您可以提出问题(或添加评论以指定在我的示例中无效的内容)。
【解决方案3】:

这方面的 SQL 相当简单...

SELECT A.Username, A.PhoneNumber, B.Message
FROM dbA.Username as A
INNER JOIN dbB.PrivateMessage as B ON A.Username = B.Username

...假设您可以在您的连接中访问这两个数据库。

如果您无法访问它们,则必须采用不同的方法(例如在查询之前将一个表复制到另一个数据库或类似的方法)。

【讨论】:

  • 我从您的代码中收到此错误消息:#1267 - 排序规则 (utf8_unicode_ci,IMPLICIT) 和 (utf8_general_ci,IMPLICIT) 用于操作 '=' 的非法混合
  • 那么你的表有不同的排序规则,所以你不能加入它们。为了执行此查询,您首先必须将它们均匀化,一种方法是ALTER TABLE dbA.Username CONVERT TO CHARACTER SET uft8 COLLATE utf8_general_ci; ALTER TABLE dbB.PrivateMessage CONVERT TO CHARACTER SET uft8 COLLATE utf8_general_ci;。请记住,这会更改表的字符集,因此请仅在以下情况下执行此操作:a)知道自己在做什么,并且 b)如果它不影响其他关键应用程序。
【解决方案4】:

试试下面的代码

SELECT * FROM dbA.Username JOIN dbB.PrivateMessage USING(Username);

【讨论】:

    猜你喜欢
    • 2017-01-30
    • 2011-06-30
    • 1970-01-01
    • 2019-03-09
    • 2013-11-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-19
    相关资源
    最近更新 更多