如何加入一到两个链接表?

时间:2015-09-04 16:30:09

标签: mysql sql

我在MySQL中有两个直接链接的表(我们称之为Event和Person)(Person有一个对应于Event中“id”的列“event_id”)。我想创建一个所有事件的视图,它们也有链接Person的名称和地址。我的假设是事件中永远不会有多个人,因此我创建了这个查询:

CREATE VIEW EventWithPerson AS
  (SELECT
    Event.id,
    Event.last_updated,
    Event.description,
    Person.name AS person_name,
    Person.address AS person_address
  FROM Event
    LEFT JOIN Person
      ON Event.id = Person.event_id);

但是,我发现有一些事件有两个对应的人(但从不超过2个)。虽然我的旧视图的列为“person_name,person_address”,但我想要创建的视图将包含“person1_name,person1_address,person2_name,person2_address”。我写的原始查询只保留其中一个人并丢弃另一个人。我怎么能修改它以保持两个人?谢谢! :)

2 个答案:

答案 0 :(得分:1)

假设id表中有Person字段,并且保证永远不会有超过2 Person行指向同一事件,您可以使用此vanilla SQL解决方案:

SELECT
    Event.id,
    Event.description,
    P1.name AS person1_name,
    P2.name AS person2_name
  FROM Event
    LEFT JOIN Person P1
      ON Event.id = P1.event_id
    LEFT JOIN Person P2
     ON Event.id = P2.event_id 
WHERE P1.id < P2.id
UNION ALL
SELECT
    Event.id,
    Event.description,
    P1.name AS person1_name,
    P2.name AS person2_name
  FROM Event
    LEFT JOIN Person P1
      ON Event.id = P1.event_id
    LEFT JOIN Person P2
     ON Event.id = P2.event_id AND P1.id <> P2.id
WHERE P2.id IS NULL

查询的第一部分仅返回具有两个匹配项的事件。第二个返回任何只有一个Person或孤儿的事件。

您可以查看here。我省略了一些列,但它们与问题无关。

答案 1 :(得分:0)

您可以使用以下查询:

SELECT id, last_updated, description,
       MAX(CASE WHEN rn = 1 THEN name END) AS person1_name,            
       MAX(CASE WHEN rn = 1 THEN address END) AS person1_address, 
       MAX(CASE WHEN rn = 2 THEN name END) AS person2_name, 
       MAX(CASE WHEN rn = 2 THEN address END) AS person2_address
FROM (
  SELECT Event.id, Event.last_updated, Event.description,
         Person.name, Person.address,
         @rn := IF(@id = Event.id,
                   IF(@id := Event.id, @rn + 1, @rn + 1),
                   IF(@id := Event.id, 1, 1)) AS rn
  FROM Event
  LEFT JOIN Person ON Event.id = Person.event_id
  CROSS JOIN (SELECT @rn:=0, @id:=0) AS vars
  ORDER BY Event.id ) AS t
GROUP BY id, last_updated, description

此查询使用变量@rn,以便将序列号分配给同一Event.id分区中的行。由于最多两个人可以与任何事件相关,@rn的最大值为2。

外部查询使用@rn来执行条件聚合。这样我们就可以将两个单独的行合并为一个,并将person1,person2数据放在不同的字段中。

Demo here