【问题标题】:MySQL require multiple values on same columnMySQL 要求同一列上有多个值
【发布时间】:2014-06-29 04:07:10
【问题描述】:

我有一些表格,其中包含一些(示例)值:

people
----------------------------------
| id    | name                   |
----------------------------------
| 1     | Steve Jobs             |
| 2     | Bill Gates             |
| 3     | Linus Torvalds         |
| 4     | Nikola Tesla           |
| 5     | Henry Ford             |
----------------------------------

.

groups
----------------------------------
| id    | name                   |
----------------------------------
| 1     | Country                |
| 2     | Work                   |
----------------------------------

.

categories
------------------------------------------
| id    | gid   | name                   |
------------------------------------------
| 1     | 1     | USA                    |
| 2     | 1     | Finland                |
| 3     | 1     | Croatia                |
| 4     | 2     | Mac                    |
| 5     | 2     | iPhone                 |
| 6     | 2     | iPad                   |
| 7     | 2     | Windows                |
| 8     | 1     | Office                 |
| 9     | 1     | Linux                  |
| 10    | 1     | Coil                   |
| 11    | 1     | El. stuff              |
| 12    | 1     | Cars                   |
------------------------------------------

.

people_categories_map
--------------------------
| id    | pid   | cid    |
--------------------------
| 1     | 1     | 1      |
| 2     | 1     | 4      |
| 3     | 1     | 5      |
| 4     | 1     | 6      |
| 5     | 1     | 11     |
| 6     | 2     | 1      |
| 7     | 2     | 7      |
| 8     | 2     | 8      |
| 9     | 2     | 11     |
| 10    | 3     | 2      |
| 11    | 3     | 9      |
| 12    | 3     | 11     |
| 13    | 4     | 1      |
| 14    | 4     | 3      |
| 15    | 4     | 10     |
| 16    | 4     | 11     |
| 17    | 5     | 1      |
| 18    | 5     | 12     |
--------------------------

挑战

我想要实现的是根据每个组的匹配项列出人员。例如,我想列出来自(国家)美国 (categories.id:1) OR 芬兰 (categories.id:2) AND Work Linux (categories.id :9) 汽车(categories.id:12)。此查询将根据 people_categories_map 表中的关系仅匹配 Linus Torvalds (people.id:3)。

但是,到目前为止,我只设法进行了列出 all 类别匹配或 any 类别匹配的查询,即:

SELECT people.id, people.name FROM people JOIN people_categories_map ON people_categories_map.pid = people.id WHERE people_categories_map.cid IN (1,2);

SELECT people.id, people.name FROM people JOIN people_categories_map ON people_categories_map.pid = people.id WHERE people_categories_map.cid IN (1,9) HAVING COUNT(DISTINCT(people_categories_map.cid)) = 2;

是否有可能以某种方式组合这些,以进行查询,返回将连接到“(category_x OR category_y) AND (category_z OR category_w OR category_m) AND (category_b OR category_c)”的人员列表等等... 换句话说,返回所有组的匹配项?

【问题讨论】:

  • 我不确定我是否理解你想要做什么......你能用其他词解释一下吗,或者再举一个例子?
  • 感谢您的回复@AlexandreFILLATRE。这是一个实际示例:我想要一个使用“汽车”或“el. stuff”的人员列表,他们必须来自“芬兰”或“克罗地亚”。这将只返回 Linus T。因为这是 people 表中唯一在两个组中都有匹配项的记录(Country 和 Work,匹配 Work:El.stuff 和 Country:Finland)......希望这个例子能解决问题小...
  • 这仍然很难理解,但我认为它来自数据模型。为什么你没有 Country 和 Work 表呢?这应该会让事情变得更容易,而且 IMO 会更有意义
  • 当然,那会容易得多。但是在 web 应用程序前端,假设使用数据库,可以添加组和类别(每个类别都是组的子)。所以组(或者可能更容易称它为主要类别和子类别)也可以是“公司”、“年龄范围”、“性别”、“城市”、“爱好”、“智商”或其他...换句话说,如果组/主要类别有自己的表,就很难有这种灵活性......但当然,更容易查询......
  • 好的。因此,按照您的示例,我看不到 Linus T. 对这两个组都进行了处理。他与类别 2、9 和 11 相关联,它们只是第 1 组的一部分。那么您的示例或数据是错误的,还是我自己错了?

标签: mysql join distinct having database-relations


【解决方案1】:

正如 Alexandre 在他的评论中所说,您的设计不仅有问题。

你的例子也有问题:T

  1. 类别 8 - 12 的 gid 应该是 2 而不是 1。
  2. 查询也应该返回“Henry Ford”,因为他住在美国,从事汽车行业。

在使用大量连接的不美观查询之后执行此操作(我确信它可以被优化,但更好地优化数据库设计):

SELECT *
FROM people_categories_map pmc1
INNER JOIN people_categories_map pmc2
ON  pmc1.pid = pmc2.pid AND pmc1.cid <> pmc2.cid
INNER JOIN people p
ON pmc1.pid = p.id
INNER JOIN categories c1
ON pmc1.cid = c1.id
INNER JOIN categories c2
ON pmc2.cid = c2.id
INNER JOIN groups g1
ON c1.gid = g1.id
INNER JOIN groups g2
ON c2.gid = g2.id
WHERE
    c1.name IN ('USA', 'FINLAND')
AND
    c2.name IN ('Linux', 'Cars');

说明

首先我们对映射表进行自联接,这样我们就可以访问国家和个人的工作。这不是真正的 INNER JOIN,因为我们的连接条件包含一个不等条件。

然后我们加入我们的人员一次,但分类和组两次:第一次是国家,第二次是工作和过滤。您可以交换这两个,而不会丢失或更改数据。这只是一个定义问题。

备注:效率不高,但我认为不值得优化。


查看fiddle for the example

如果您只想要一个人一次,请使用

SELECT DISTINCT p.id, p.name
FROM ...

【讨论】:

  • 我投票赞成你的答案,因为你比我走得更远,但我不确定这是最好的方法,主要是因为你必须指出 C1 和 C2 的名称。无论如何,这似乎非常接近我们可以用这个设计做的最好的。
  • 感谢您的回复。正如你们都指出的那样,类别表在 gid col 中有错误,因为 id 8-12 应该是 gid:2 ...对此感到抱歉。我会试试你的例子@VMai。但是,设计并非一成​​不变(该项目处于早期设计阶段),因此非常感谢任何设计更改建议,谢谢 :) 重要的是主要类别(如 Country、Work 等)及其子类别(如 USA ,芬兰等)不是静态的,从某种意义上说,主要类别(组)和子类别(类别)可以在不改变数据库结构的情况下添加、更改和删除..
  • @user3626415 你可以玩fiddle的where子句。
  • 感谢 VMai 花时间制作小提琴,我明天(当地时间 00.40 ;) 会更多地使用它...
  • 我不同意这是低效的
猜你喜欢
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多