【发布时间】:2020-04-05 16:29:05
【问题描述】:
使用 GROUP BY 命令,可以 LEFT JOIN 多个表,并且仍然可以从第一个表中获取所需的行数。
例如,
SELECT b.title
FROM books `b`
LEFT JOIN orders `o`
ON o.bookid = b.id
LEFT JOIN authors `a`
ON b.authorid = a.id
GROUP BY b.id
但是,由于 MYSQL 在幕后对表进行笛卡尔积,如果包含多个 SUM 命令,则基于所有隐藏行会得到不正确的值。 (这里的问题是explained 相当不错。)
SELECT b.title,SUM(o.id) as sales,SUM(a.id) as authors
FROM books `b`
LEFT JOIN orders `o`
ON o.bookid = b.id
LEFT JOIN authors `a`
ON b.authorid = a.id
GROUP BY b.id
在 SO 上有很多 answers 与此有关,大多数在 JOINS 中使用子查询,但我无法将它们应用于这个相当简单的案例。
如何调整以上内容以获得正确的 SUM?
编辑
例子
books
id|title|authorid
1|Huck Finn|1
2|Tom Sawyer|1
3|Python Cookbook|2
orders
id|bookid
1|1
2|1
3|2
4|2
5|3
6|3
authors
id|author
1|Twain
2|Beazley
2|Jones
Python Cookbook 的作者总数 # 的“正确答案”是 2。但是,因为有两个连接,并且整个数据集通过连接订单数进行扩展,所以 SUM(a.id) 将为 4 .
【问题讨论】:
-
您能否详细说明“...正确的 SUM”?请添加一些示例数据和预期结果。
-
见上面的例子
-
当它不是表的 ID 时,将其称为
authors.id真是个坏主意。这是一个糟糕的数据模型。您应该有一个包含唯一作者的作者表和一个桥接表来表示书籍和作者之间的 m:n 关系。 -
请在代码问题中给出minimal reproducible example--cut & paste & runnable code,包括最小的代表性示例输入作为代码;期望和实际输出(包括逐字错误消息);标签和版本;明确的规范和解释。给出您可以给出的最少代码,即您显示的代码可以通过您显示的代码扩展为不正常。 (调试基础。)对于包含 DBMS 和 DDL(包括约束和索引)和输入为格式化为表的代码的 SQL。请不要发布无效代码作为描述,它没有任何意义。用文字将输出解释为输入的函数。
-
这似乎是一个常见错误,人们想要一些连接,每个可能涉及不同的键,一些子查询,每个可能涉及连接和/或聚合,但他们错误地尝试执行所有然后加入所有聚合或聚合以前的聚合。在适当的行上写单独的总和和/或总结一个案例语句选择行;加入常见的唯一列集。了解 LEFT JOIN ON 返回什么: INNER JOIN ON rows UNION ALL 不匹配的左表行,由 NULL 扩展。作为 OUTER JOIN ON 的一部分,始终知道您想要什么 INNER JOIN ON。