始终为0或更多)。我认为,即使是NULL,SUM()也应该正确地计算NULL的值?(对于检查,如果它将执行5+0+3+NULL+2-NULL将不会在MySQL的SUM()中自动被视为0?或者这将产生一些错误?)。删除它,您将看到。您的假设对于COUNT()
始终为0或更多)。我认为,即使是NULL,SUM()也应该正确地计算NULL的值?(对于检查,如果它将执行5+0+3+NULL+2-NULL将不会在MySQL的SUM()中自动被视为0?或者这将产生一些错误?)。删除它,您将看到。您的假设对于COUNT(),mysql,join,distinct,Mysql,Join,Distinct,始终为0或更多)。我认为,即使是NULL,SUM()也应该正确地计算NULL的值?(对于检查,如果它将执行5+0+3+NULL+2-NULL将不会在MySQL的SUM()中自动被视为0?或者这将产生一些错误?)。删除它,您将看到。您的假设对于COUNT()是正确的,但对于SUM()则不正确。如果SUM()根本没有值(用户没有订单),它将返回NULL“您正在将来自一个用户的订单与来自同一网络的所有其他用户合并”-但我对一个合并使用“u”shortname,对另一个合并使用“un”shortname
始终为0或更多)。我认为,即使是NULL,SUM()也应该正确地计算NULL的值?(对于检查,如果它将执行5+0+3+NULL+2-NULL将不会在MySQL的SUM()中自动被视为0?或者这将产生一些错误?)。删除它,您将看到。您的假设对于
COUNT()
是正确的,但对于SUM()
则不正确。如果SUM()
根本没有值(用户没有订单),它将返回NULL
“您正在将来自一个用户的订单与来自同一网络的所有其他用户合并”-但我对一个合并使用“u”shortname,对另一个合并使用“un”shortname,因此用户表应该独立合并,或者这不是JOIN在MySQL中的工作方式?如果我将连接同一个表几次(不管是短名称),它将与同一个表的每个连接合并吗?因此,我应该避免在一个查询中对同一个表名使用JOIN,并且应该始终将其划分为子查询?将一个表与其自身连接不是问题。问题是在同一FROM子句中连接两个独立的一对多关系。关于您的第一条注释-请参阅:“如果返回集没有行,SUM()返回NULL”和“如果没有匹配行,SUM()返回NULL。”-SUM()
没有将NULL转换为0
,只是忽略它们。这就是为什么SUM(5+0+3+NULL+2)
有效的原因-它相当于SUM(5+0+3+2)
“通常解决方法是首先设计一个查询,使用从中间表获得正确和所需的最小表数。”-因此建议将此SQL划分为两个单独的SQL请求?一个用于获取count()和sum(),另一个用于获取具有不同联接的所有其他人员?@Dmitry-通常不需要单独的SQL。我添加了一个“派生表”的示例。Arth也有一个例子。有趣的想法,谢谢有趣的三种方法中,哪一种在大型数据库上运行得更快(按性能衡量)。@Dmitry欢迎您!我真的不知道,我认为这三种方法在工作方面是可以比较的,所以这将取决于它们如何与你现有的任何索引交互。。我建议尝试不同的选项并解释选择
SELECT u.*,
count(o.id) AS total_orders,
sum(o.total) AS total_revenue,
count(un.userid) as network_users /* Users count in same network */
FROM users u
LEFT JOIN orders o ON o.userid=u.userid
LEFT JOIN users am ON u.ownerid = am.userid
LEFT JOIN users bdr ON u.bdrid = bdr.userid
LEFT JOIN networks n ON u.networkid = n.networkid
LEFT JOIN users un ON n.networkid=un.networkid
GROUP BY u.userid
ORDER BY u.userid DESC;
SELECT u.userid,
count(o.id) AS total_orders,
coalesce(sum(o.total), 0) AS total_revenue,
(
SELECT count(*)
FROM users un
WHERE un.networkid = u.networkid
) as network_users
FROM users u
LEFT JOIN orders o ON o.userid=u.userid
GROUP BY u.userid, u.networkid
ORDER BY u.userid DESC;
| userid | total_orders | total_revenue | network_users |
| ------ | ------------ | ------------- | ------------- |
| 40 | 1 | 75 | 1 |
| 37 | 0 | 0 | 2 |
| 33 | 0 | 0 | 1 |
| 24 | 3 | 175 | 2 |
SELECT u.userid,
count(o.id) AS total_orders,
coalesce(sum(o.total), 0) AS total_revenue,
u.network_users
FROM (
SELECT u.userid, count(un.userid) as network_users
FROM users u
LEFT JOIN users un ON un.networkid = u.networkid
GROUP BY u.userid
) u
LEFT JOIN orders o ON o.userid=u.userid
GROUP BY u.userid
ORDER BY u.userid DESC;
| userid | network_users | total_orders | total_revenue |
| ------ | ------------- | ------------ | ------------- |
| 40 | 1 | 1 | 75 |
| 37 | 2 | 0 | 0 |
| 33 | 1 | 0 | 0 |
| 24 | 2 | 3 | 175 |
SELECT ...
FROM ( SELECT key, COUNT(*), SUM(..) FROM .. GROUP BY .. ) AS a
JOIN b ON ...
JOIN c ON ...
SELECT agg.userid,
SUM(agg.order_count) AS total_orders,
SUM(agg.revenue_sum) AS total_revenue,
SUM(agg.network_user_count) AS network_users
FROM (
/** Orders and Revenue */
SELECT u.userid,
COUNT(o.id) AS order_count,
SUM(o.total) AS revenue_sum,
0 AS network_user_count
FROM users u
LEFT JOIN orders o ON o.userid=u.userid
GROUP BY u.userid
UNION ALL
/** Network Users */
SELECT u.userid,
0 AS order_count,
0 AS revenue_sum,
COUNT(un.userid) AS network_user_count
FROM users u
LEFT JOIN users un
ON un.networkid = u.networkid
GROUP BY u.userid
) agg
GROUP BY agg.userid
ORDER BY agg.userid DESC;
| userid | order_count | revenue_sum | network_user_count |
| ------ | ----------- | ----------- | ------------------ |
| …
| 24 | 3 | 175 | 0 |
| 24 | 0 | 0 | 2 |
| …