上下文:
我正在开发一个简单的 ORM(适用于 PHP),它基于静态配置自动执行大多数查询。
因此,根据表和实体定义,库会自动处理连接并生成适当的字段/表别名...对于 LEFT 连接没有问题,但在关系一对多的情况下,INNER 可能会导致重复的结果。 我的想法是在必要时自动添加一个 GROUP BY 子句(在自动增量键上)。
问题
当(且仅当)联接的 ON 和 WHERE 条件与联接表的唯一键不匹配时,认为我需要添加 GROUP BY 子句是否正确?
示例
一个非常简单的示例,我想选择(至少)具有关联显示的所有事件。 如果有其他方法可以在不使用 INNER JOIN 的情况下完成此操作,我很想知道如何实现:)
CREATE TABLE `Event` (
`Id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`Name` VARCHAR(255) NOT NULL
);
INSERT INTO `Event` (`Name`) VALUES ('My cool event');
CREATE TABLE `Showing` (
`Id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
`EventId` INT UNSIGNED NOT NULL,
`Place` VARCHAR(50) NOT NULL,
FOREIGN KEY (`EventId`) REFERENCES `Event`(`Id`),
UNIQUE (`EventId`, `Place`)
);
INSERT INTO `Showing` (`EventId`, `Place`) VALUES (1, 'School');
INSERT INTO `Showing` (`EventId`, `Place`) VALUES (1, 'Park');
-- Correct queries
SELECT t.* FROM `Event` t INNER JOIN `Showing` t1 ON t.Id=t1.`EventId` WHERE t1.`PlaceId` = 'School';
SELECT t.* FROM `Event` t INNER JOIN `Showing` t1 ON t.Id=t1.`EventId` AND t1.`PlaceId` = 'School';
-- Query leading to duplicate values
SELECT t.* FROM `Event` t INNER JOIN `Showing` t1 ON t.Id=t1.`EventId`;
-- Group by query to prevent duplicate values
SELECT t.* FROM `Event` t INNER JOIN `Showing` t1 ON t.Id=t1.`EventId` GROUP BY t.`Id`;
谢谢!
最佳答案
(这应该是一条评论,但有点长)
No problem for LEFT joins but INNER may result in duplicated results in case of relation One-to-Many
从这句话中可以清楚地看出,我们中至少有一个人对关系数据库如何工作以及对象关系映射应该如何工作感到非常困惑。
Query leading to duplicate values
生成的行不是重复的 - 您已经编写了查询,因此它不会向您显示它们为何不同:
SELECT t1.place, t.*
FROM Event
INNER JOIN Showing
ON Event.Id=Showing.EventId;
如果您对“显示”中的数据不感兴趣,那么为什么它会出现在您的查询中?如果您的事件没有相关的放映记录,那么您应该使用“EXISTS” - 而不是联接(考虑您有一个事件但有 300 万次放映)
SELECT t1.place, t.*
FROM `Event` t
WHERE EXISTS (SELECT 1
FROM Showing
WHERE Event.Id=Showing.EventId);
如果您严格实现 ORM,那么您可能根本不应该编写带有连接的查询 - 但恕我直言,使用工厂可以更好地满足该场景。
关于mysql - INNER JOIN 和 GROUP BY 以防止重复结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32870554/