【问题标题】:how to use a like with a join in sql?如何在sql中使用like和join?
【发布时间】:2010-11-26 01:10:54
【问题描述】:

我有 2 个表,比如表 A 和表 B,我想执行连接,但匹配条件必须是 A 中的列“就像”B 中的列,这意味着任何东西都可以在之前或之后出现B中的列:

例如:如果 A 中的列是 'foo'。如果 B 中的列是“fooblah”、“somethingfooblah”或只是“foo”,则连接将匹配。我知道如何在标准的 like 语句中使用通配符,但在进行连接时感到困惑。这有意义吗?谢谢。

【问题讨论】:

    标签: mysql sql join sql-like


    【解决方案1】:

    使用INSTR

    SELECT *
      FROM TABLE a
      JOIN TABLE b ON INSTR(b.column, a.column) > 0
    

    使用喜欢:

    SELECT *
      FROM TABLE a
      JOIN TABLE b ON b.column LIKE '%'+ a.column +'%'
    

    将 LIKE 与 CONCAT 一起使用:

    SELECT *
      FROM TABLE a
      JOIN TABLE b ON b.column LIKE CONCAT('%', a.column ,'%')
    

    请注意,在所有选项中,您可能希望在比较之前将列值驱动为大写,以确保获得匹配项而不考虑区分大小写:

    SELECT *
      FROM (SELECT UPPER(a.column) 'ua'
             TABLE a) a
      JOIN (SELECT UPPER(b.column) 'ub'
             TABLE b) b ON INSTR(b.ub, a.ua) > 0
    

    最高效的最终取决于EXPLAIN plan 输出。

    JOIN 子句与编写 WHERE 子句相同。 JOIN 语法也称为 ANSI JOIN,因为它们是标准化的。非 ANSI JOIN 看起来像:

    SELECT *
      FROM TABLE a,
           TABLE b
     WHERE INSTR(b.column, a.column) > 0
    

    我不会为非 ANSI LEFT JOIN 示例而烦恼。 ANSI JOIN 语法的好处在于它将连接表的内容与WHERE 子句中实际发生的内容分开。

    【讨论】:

    • LIKE 和 INSTR 之间的最佳速度是多少(例如域名)?
    • 一直说:JOIN 中遇到左右别名
    • hmm 加入类似的作品但停止使用索引,我在列上添加了索引,知道吗?
    【解决方案2】:

    在 MySQL 中你可以试试:

    SELECT * FROM A INNER JOIN B ON B.MYCOL LIKE CONCAT('%', A.MYCOL, '%');

    当然,这将是一个非常低效的查询,因为它会进行全表扫描。

    更新:这是一个证明

    
    create table A (MYCOL varchar(255));
    create table B (MYCOL varchar(255));
    insert into A (MYCOL) values ('foo'), ('bar'), ('baz');
    insert into B (MYCOL) values ('fooblah'), ('somethingfooblah'), ('foo');
    insert into B (MYCOL) values ('barblah'), ('somethingbarblah'), ('bar');
    SELECT * FROM A INNER JOIN B ON B.MYCOL LIKE CONCAT('%', A.MYCOL, '%');
    +-------+------------------+
    | MYCOL | MYCOL            |
    +-------+------------------+
    | foo   | fooblah          |
    | foo   | somethingfooblah |
    | foo   | foo              |
    | bar   | barblah          |
    | bar   | somethingbarblah |
    | bar   | bar              |
    +-------+------------------+
    6 rows in set (0.38 sec)
    

    【讨论】:

    • 谢谢..我怎样才能实现相同的功能但更高效?
    • 这就是你的做法。如果您需要它更高效,您可以索引表 B 上的 MYCOL 字段。
    • 如果您使用的是 MyISAM 表类型,您可以尝试全文索引,看看是否有帮助。不过一般来说,全文搜索并不是 MySQL 的强项。如果全文搜索是您应用程序的核心部分,请考虑类似 Apache Lucene - lucene.apache.org/java/docs
    • 更新:顺便说一句:全文索引需要不同的查询。有关详细信息,请参阅此处的 MySQL 文档:dev.mysql.com/doc/refman/5.0/en/fulltext-search.html
    【解决方案3】:

    如果这是您需要经常做的事情……那么您可能想要非规范化表 A 和 B 之间的关系。

    例如,在插入表 B 时,您可以将零个或多个条目写入基于部分映射将 B 映射到 A 的联结表。同样,对任一表的更改都可以更新此关联。

    这完全取决于表 A 和 B 的修改频率。如果它们是相当静态的,那么在 INSERT 上点击会比在 SELECT 上重复点击更不痛苦。

    【讨论】:

    • 这是一个很好的解决方案,但称其为非规范化并不准确。
    • 很公平。然后将其称为连接表
    【解决方案4】:

    在连接中使用条件条件绝对不同于 Where 子句。表之间的基数可能会在 Join 和 Where 子句之间产生差异。

    例如,在外部联接中使用 Like 条件将保留联接中列出的第一个表中的所有记录。在 Where 子句中使用相同的条件将隐式地将连接更改为内部连接。记录通常必须出现在两个表中,才能完成 Where 子句中的条件比较。

    我通常使用之前答案之一中给出的样式。

    tbl_A as ta
        LEFT OUTER JOIN tbl_B AS tb
                ON ta.[Desc] LIKE '%' + tb.[Desc] + '%'
    

    这样我可以控制连接类型。

    【讨论】:

      【解决方案5】:

      当使用我们的服务器 LIKE 或 INSTR(或 T-SQL 中的 CHARINDEX)编写查询需要太长时间,因此我们使用 LEFT,如下结构:

      select *
      from little
      left join big
      on left( big.key, len(little.key) ) = little.key
      

      我知道这可能只适用于查询的不同 结尾,这与其他使用 '%' + b + '%' 的建议不同,但如果您只需要 b+'% 就足够了,而且速度更快'。

      另一种优化速度(但不是内存)的方法是在“little”中创建一个列,即“len(little.key)”作为“lenkey”,而不是在上面的查询中创建一个用户。

      【讨论】:

      • 我知道这不能回答 OP 的问题,但它确实回答了我的问题,感谢您提供的示例,因为我的查询匹配了数百万条记录。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多