我在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”。我写的原始查询只保留其中一个人并丢弃另一个人。我怎么能修改它以保持两个人?谢谢! :)
答案 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数据放在不同的字段中。