SQL将表B中的两个或多个与表A中的公共数据连接起来

时间:2010-03-31 20:47:59

标签: sql mysql

注意:已编辑

现实世界的情况是一系列事件,每个事件都有两个或更多参与者(如运动队,但事件中可能有两个以上),其中只有一个是事件的主持人。每个唯一事件都有一个事件数据库表,一个包含唯一参与者的参与者数据库表。它们使用Matchup表连接在一起。它们看起来像这样:

事件

EventID(PK)
(其他事件数据,如日期等)

参与者

ParticipantID(PK)
姓名

对决

EventID(FK到事件表)
参与者ID(参与者的FK)
主机(1或0,每个EventID只有1个主机= 1)

如果我知道有两个参与者,我希望得到的结果是这样的:

EventID  PID-1(host)  Name-1 (host)  PID-2  Name-2
-------  -----------  -------------  -----  ------
    1         7       Lions            8    Tigers
    2        11       Dogs             9    Cats

同样,如果我知道有三个参与者,我将如何做同样的事情?

我怀疑答案是相当简单的,但出于某种原因,我并没有把头包裹起来。或者,它非常困难。 :)

如果这会影响可用的SQL,我正在使用MYSQL。

1 个答案:

答案 0 :(得分:1)

CREATE TABLE event (
  pk int PRIMARY KEY
);

CREATE TABLE participant (
  pk int PRIMARY KEY,
  name varchar(255)
);

CREATE TABLE matchup (
  e int,
  p int,
  isHost bit,
  CONSTRAINT PK_matchup PRIMARY KEY (e,p)
);

-- Events with 2 particpants
INSERT INTO event (pk) VALUES (1);
INSERT INTO event (pk) VALUES (2);
INSERT INTO participant (pk, name) VALUES (7, 'Lions');
INSERT INTO participant (pk, name) VALUES (8, 'Tigers');
INSERT INTO participant (pk, name) VALUES (11, 'Dogs');
INSERT INTO participant (pk, name) VALUES (9, 'Cats');
INSERT INTO matchup (e, p, isHost) VALUES (1, 7, 1);
INSERT INTO matchup (e, p, isHost) VALUES (1, 8, 0);
INSERT INTO matchup (e, p, isHost) VALUES (2, 11, 1);
INSERT INTO matchup (e, p, isHost) VALUES (2, 9, 0);

-- Events with 3 particpants
INSERT INTO event (pk) VALUES (3);
INSERT INTO participant (pk, name) VALUES (1, 'One');
INSERT INTO participant (pk, name) VALUES (2, 'Two');
INSERT INTO participant (pk, name) VALUES (3, 'Three');
INSERT INTO matchup (e, p, isHost) VALUES (3, 1, 0);
INSERT INTO matchup (e, p, isHost) VALUES (3, 2, 1);
INSERT INTO matchup (e, p, isHost) VALUES (3, 3, 0);

-- SELECT the events with 2 participants
SELECT
  event.pk AS EventID,
  p1.pk    AS Pid1_Host,
  p1.name  AS Name1_Host,
  p2.pk    AS Pid2,
  p2.name  AS Name2
FROM
             event
  INNER JOIN matchup m1 ON (event.pk = m1.e)
  INNER JOIN matchup m2 ON (event.pk = m2.e)
  INNER JOIN participant p1 ON (m1.isHost = 1 AND m1.p = p1.pk)
  INNER JOIN participant p2 ON (m2.isHost != 1 AND m2.p = p2.pk)
WHERE
  event.pk IN (SELECT e FROM matchup GROUP BY e HAVING COUNT(*) = 2)

+---------+-----------+------------+------+--------+
| EventID | Pid1_Host | Name1_Host | Pid2 | Name2  |
+---------+-----------+------------+------+--------+
|       1 |         7 | Lions      |    8 | Tigers |
|       2 |        11 | Dogs       |    9 | Cats   |
+---------+-----------+------------+------+--------+
2 rows in set (0.00 sec)


-- SELECT the events with 3 participants
SELECT
  event.pk AS EventID,
  p1.pk    AS Pid1_Host,
  p1.name  AS Name1_Host,
  p2.pk    AS Pid2,
  p2.name  AS Name2,
  p3.pk    AS Pid3,
  p3.name  AS Name3
FROM
             event
  INNER JOIN matchup m1 ON (event.pk = m1.e)
  INNER JOIN matchup m2 ON (event.pk = m2.e)
  INNER JOIN matchup m3 ON (event.pk = m3.e)
  INNER JOIN participant p1 ON (m1.isHost = 1 AND m1.p = p1.pk)
  INNER JOIN participant p2 ON (m2.isHost != 1 AND m2.p = p2.pk)
  INNER JOIN participant p3 ON (m3.isHost != 1 AND m3.p = p3.pk AND p3.pk != p2.pk)
WHERE
      p2.pk < p3.pk -- to remove spurious rearrangements of Name2 and Name3
  AND event.pk IN (SELECT e FROM matchup GROUP BY e HAVING COUNT(*) = 3)


+---------+-----------+------------+------+-------+------+-------+
| EventID | Pid1_Host | Name1_Host | Pid2 | Name2 | Pid3 | Name3 |
+---------+-----------+------------+------+-------+------+-------+
|       3 |         2 | Two        |    1 | One   |    3 | Three |
+---------+-----------+------------+------+-------+------+-------+
1 row in set (0.00 sec)