【问题标题】:One to Many Search Query一对多搜索查询
【发布时间】:2013-09-16 13:30:47
【问题描述】:

我有一个 MySQL 表,我在其中保持一对多的关系。该表用于存储足球统计程序的合作伙伴列表。一个玩家可以有 0、1 或 2 个伙伴。

例如:

___________________________________
| Table index | Partners | Players |
|      1      |     1    |  John   | - Singles, no partners
|      2      |     2    |  John   | - Doubles, John and Bob
|      3      |     2    |  Bob    | - Doubles, John and Bob
|      4      |     3    |  Dave   | - Roto doubles, Dave, Bob, John
|      5      |     3    |  Bob    | - Roto doubles, Dave, Bob, John
|      6      |     3    |  John   | - Roto doubles, Dave, Bob, John
|      7      |     4    |  Dave   | - Singles, no partners
____________________________________

我正在编写 PHP 脚本以从表中添加和检索合作伙伴,但我的查询遇到了问题。我了解玩家并想检索合作伙伴字段。我需要执行三个查询:

  • 检查没有合作伙伴 - 单身人士;
  • 检查特定合作伙伴 - 与“Dave”双打;
  • 检查两个特定的合作伙伴 - 与“鲍勃和戴夫”双打;

如果条目存在,我想检索它,如果不存在,那么我会将该条目添加到表中。我遇到的麻烦之一是,例如,玩家“约翰”有三个条目,没有伙伴,一个伙伴,两个伙伴。如何指定只拉出条目 1 而不是 2 或 6?

我在这里搜索并找到了几个接近但不完全符合我需要的示例。这个mySQL: Querying one-to-many -table? 几乎可以满足我的需要,但并不完全。

任何帮助将不胜感激。

克里斯

【问题讨论】:

  • 为什么最后一行,四个合伙人,意思是“单身没有合伙人”?
  • 您只保留派生信息 - 这将难以维护。您是否还需要输入谁与谁合作的信息?在这种情况下,只需维护一个合作伙伴表,并通过查询得出每个玩家的合作伙伴数量。
  • 抱歉,列标题“partners”最好命名为“partnerID”。它是指示伴侣关系的指标,而不是特定人拥有的伴侣数量。我的原始帖子可能具有误导性。

标签: php mysql one-to-many


【解决方案1】:

如果我正确理解您的架构,您的 Partners 字段实际上是隐式分组表的外键(即,最好将其命名为 TeamId 并将键放入名为 Team 的表中,其中每一行代表一个合作伙伴关系)。

让我们定义完整的模式,以便我们可以正常工作(这与您的表基本相同,但进行了非规范化以使其更清晰,您也可以只使用 PlayerId 而不是允许具有相同名称的不同玩家的名称)。您的多对多连接器表是 PlayerTeam。

我们可以通过运行此查询来获取给定玩家的 TeamId 和团队规模

SELECT TeamId, count(PlayerId) as TeamSize
FROM PlayerTeam
WHERE TeamId IN (SELECT TeamId FROM PlayerTeam WHERE PlayerId = *your-player-id*)
GROUP BY TeamId

您可以通过添加 HAVING 子句来获得特定规模的团队:

SELECT TeamId, count(PlayerId) as TeamSize
FROM PlayerTeam
WHERE TeamId IN (SELECT TeamId FROM PlayerTeam WHERE PlayerId = *your-player-id*)
GROUP BY TeamId
HAVING TeamSize = 2 

您还可以通过使用此查询避免每个玩家查询一次:

SELECT p.Name, p.PlayerId, pt.TeamId, sz.TeamSize
FROM Player p JOIN PlayerTeam pt USING(PlayerId)
   JOIN (SELECT TeamId, count(PlayerId) as TeamSize
         FROM PlayerTeam GROUP BY TeamId) AS sz USING(TeamId)

但要有效地使用最后一个,您需要使用结果来准备一个索引方便的关联数组(如$team[UserId][TeamSize] => TeamId)来做出决定。

【讨论】:

  • 您的架构几乎是正确的,我有单独的球员姓名表,并在 PlayerTeam 表中使用他们的索引。我认为 TEAM 表与这些查询无关。这些查询正是我正在寻找的。另一种情况是,如果我知道三个或所有三个球员的信息。我想我必须扩展第一个和第二个查询的 WHERE 选项?
  • 你是对的,Team 表没有被使用,我把它放在那里是因为它有助于多对多的直觉。是的,拥有另一个带有子查询的 IN 子句将允许您指定多个团队成员:... WHERE TeamId IN (SELECT TeamId FROM PlayerTeam WHERE PlayerId = id1) AND TeamId IN (SELECT TeamId FROM PlayerTeam WHERE PlayerId = id2) ...。但是不确定它的性能如何,但是如果以后它成为问题,您可以解决它。
  • 非常感谢。我能够让查询完美地工作。添加额外的玩家 ID 检查效果很好。
猜你喜欢
  • 2013-06-27
  • 1970-01-01
  • 2013-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多