MySQL查询以匹配不相关的术语

MySQL查询以匹配不相关的术语,mysql,select,subquery,Mysql,Select,Subquery,我试图构造一个让我发疯的查询。我不知道从哪里开始解决它,但在搜索了一点之后,我开始玩子查询。现在我不确定这是否能解决我的问题,或者,如果能,如何创建一个符合我要求的解决方案 下面是我当前表格的一个非常简单的视图(称之为tbl_1): 我正在处理的一些项目有多个名称(品牌名称、其他国家的名称、代号等),但最终所有这些不同的名称都指向同一个项目。我最初是按照以下内容运行搜索查询: SELECT * FROM tbl_1 WHERE name LIKE '%A%' OR other_names LIK

我试图构造一个让我发疯的查询。我不知道从哪里开始解决它,但在搜索了一点之后,我开始玩子查询。现在我不确定这是否能解决我的问题,或者,如果能,如何创建一个符合我要求的解决方案

下面是我当前表格的一个非常简单的视图(称之为tbl_1):

我正在处理的一些项目有多个名称(品牌名称、其他国家的名称、代号等),但最终所有这些不同的名称都指向同一个项目。我最初是按照以下内容运行搜索查询:

SELECT * FROM tbl_1
WHERE name LIKE '%A%'
OR other_names LIKE '%A%';
它将返回第1行和第3行。然而,我很快意识到,我的查询也应该返回第2行,如A=B=C。我该怎么做呢?除了一个奇特的查询之外,我愿意接受其他的建议,例如构建另一个表,以某种方式将所有名称组合到一行中,但我认为这样做容易出错或效率低下

此外,我正在使用InnoDB运行MySQL 5.5.23,并使用PHP和Python编写的其他代码

谢谢

2012年5月26日更新:
我回到了使用子查询的最初想法,但就在我认为我正在取得进展的时候,我遇到了一个有文档记录的MySQL问题,在这个问题上,查询是从外部到内部进行评估的,我的子查询将针对每一行进行评估,并且不会在实际的时间内完成。以下是我试图做的:

SELECT * FROM tbl_1
WHERE name = ANY
    (SELECT name FROM tbl_1 WHERE other_names LIKE '%A%' or name LIKE '%A%')
OR other_names = ANY 
    (SELECT name FROM tbl_1 WHERE other_names LIKE '%A%' or name LIKE '%A%')
它使用示例表返回我想要的结果,但是前面提到的MySQL问题/错误导致子查询被视为依赖查询而不是独立查询。因此,我无法在实际表(约250000行)上测试查询,因为它最终超时

我已经读到这个问题的主要解决方法是使用联接而不是子查询,但我不确定如何将其应用到我正在尝试的工作中。我想得越多,我最好使用PHP/Python独立运行子查询,并使用生成的数组来创建我想要的主查询。但是,我仍然认为可能会遗漏一些结果,因为列中的术语没有我的示例那么好(有些术语是多个单词,有些有括号,其他名称不一定是逗号分隔的,等等)

或者,我正在考虑构建一个单独的表来构建必要的链接,比如:

| 1 | A | B, C|
| 2 | B | C, A|
| 3 | C | A, B|
但考虑到我所处理的数据以及数据存在的非标准化格式,我认为这说起来容易做起来难

我在这一点上强烈考虑的方法是使用易于构造的链接(即名称与其他名称的比例为1:1)构建一个单独的表,这样我就不必处理其他名称列中存在的格式问题。我还可以消除/限制LIKE的使用,并要求用户至少知道一个确切的名称,以简化结果,并可能提高整体性能


总之,我讨厌处理我无法控制的输入数据。

我想不出一个支持无限深度名称标识的查询。但是,如果您可以使用有限数量的“递归”,则可以考虑使用类似于此的查询,从提供的查询开始,检索具有名称标识的所有行:

SELECT a.* FROM tbl_1 a
WHERE a.name='A'
OR a.other_names LIKE '%A%'
UNION
SELECT b.* FROM tbl_1 a
JOIN tbl_1 b ON a.other_names LIKE '%' || b.name || '%' OR b.other_names LIKE '%' || a.name || '%'
WHERE a.name='A'
OR a.other_names LIKE '%A%';
此查询将返回第2行,但在您的示例中,它不会返回任何将“B”作为“other_name”的其他行。因此,您必须合并另一个查询:

SELECT a.* FROM tbl_1 a
WHERE a.name='A'
OR a.other_names LIKE '%A%'
UNION
SELECT b.* FROM tbl_1 a
JOIN tbl_1 b ON a.other_names LIKE '%' || b.name || '%' OR b.other_names LIKE '%' || a.name || '%'
WHERE a.name='A'
OR a.other_names LIKE '%A%';
UNION
SELECT c.* FROM tbl_1 a
JOIN tbl_1 b ON (a.other_names LIKE '%' || b.name || '%' OR b.other_names LIKE '%' || a.name || '%')
JOIN tbl_1 c ON (b.other_names LIKE '%' || c.name || '%' OR c.other_names LIKE '%' || b.name || '%')
WHERE a.name='A'
OR a.other_names LIKE '%A%';

正如您所看到的,查询将随着深度的增加而快速增长和加速,而这也不是我所说的美丽。但它可能适合你的需要。我在使用MySQL函数方面不是很有经验,但我想您可以创建一个更优雅的解决方案,也可以使用这些函数进行无限深度的工作。你也可以考虑用Python编程解决这个问题。

意外地碰到这个问题,所以我不知道我的建议是否相关,但是这看起来像是一个“联合发现”的好用法。

选择将非常简单和快速。 但是insert&update相对比较复杂,您可能需要一个代码内循环(当更新的行>0时)。。。还有几个数据库调用

表格示例:

---------------------------
|  row |  name  |  group  |
|-------------------------|
|   1  |   A    |    1    |
|   2  |   B    |    1    |
|   4  |   C    |    1    |
|   5  |   D    |    2    |
|   6  |   X    |    1    |
|   7  |   Z    |    2    |
---------------------------
选择: 从
tbl
WHERE
group
=(从
tbl
WHERE
name
中选择
group
,如“%A%”)


插入关系K=T:(psedu codeish.)

选择
group
作为gk,其中name=K; 选择
group
作为gt,其中name=T

如果(gk空结果)和(gt空结果)都与新组一起插入

---------------------------
|  row |  name  |  group  |
|-------------------------|
|   1  |   A    |    1    |
|   2  |   B    |    1    |
|   4  |   C    |    1    |
|   5  |   D    |    2    |
|   6  |   X    |    1    |
|   7  |   Z    |    2    |
|   8  |   K    |    3    |
|   9  |   T    |    3    |
---------------------------
如果(gk空结果)和(gt非空结果)插入t,组=gx.group

---------------------------
|  row |  name  |  group  |
|-------------------------|
|   1  |   A    |    1    |
|   2  |   B    |    1    |
|   4  |   C    |    1    |
|   5  |   D    |    2    |
|   6  |   X    |    1    |
|   7  |   Z    |    2    |
|   8  |   K    |    2    |
|   9  |   T    |    2    |
---------------------------
(另一种情况相同)

当两者都不为空时,将一个组更新为另一个组


更新
tbl1
SET group=gt,其中group=gk

只是试图理解表结构,如果B实际上只是A的另一个名称,而不是为什么它有一个单独的行(第2行)?@coder行中的数据由用户填充,这些用户不一定知道某个东西的所有名称。更具体地说,这些名称指的是药品。在美国,人们可能知道Incivek=telaprevir,并将其作为输入(Incivek的名称,telaprevir的其他名称),但在欧洲,它也被称为Incivo。因此,一个人可能正在搜索“Incivek”,但它也应该调出Incivo的结果。谢谢!由于实际问题(我的表有200000多行),这并不能真正解决我的问题,但您提到的递归让我很快意识到这实际上是多么困难。此时,我想我将尝试使用python处理输入数据,并创建一个包含所有正确链接的单独表。
---------------------------
|  row |  name  |  group  |
|-------------------------|
|   1  |   A    |    1    |
|   2  |   B    |    1    |
|   4  |   C    |    1    |
|   5  |   D    |    2    |
|   6  |   X    |    1    |
|   7  |   Z    |    2    |
|   8  |   K    |    2    |
|   9  |   T    |    2    |
---------------------------