我会尽力直截了当地想要在这里完成......
我有一个有效的查询,但我最近发现了一个问题。现在,我可以简单地用PHP修复它,但我知道它可以在MySQL中以某种方式完成...我只是不知道如何。所以这就是:
我有一个USERS表和一个SERVICES表。用户可以拥有多个服务(每个服务彼此完全独立),并且每个服务都有一个名为“status”的字段。状态定义服务所处的当前状态:活动/非活动
当您转到“管理用户”页面时,将调用该查询,其中每个用户都将拆分为其所属的类别。对于此示例,它将是:活动用户|已停用的用户|其他用户(完全没有任何服务计划的用户)。
所以我的停用用户查询归结为:
SELECT DISTINCT u.* FROM users u LEFT JOIN services s ON s.assignedto=u.id WHERE s.status!=1
该声明很有效,但是,如果客户有2个服务计划,其中一个被激活而另一个被停用,那么他将出现在已停用的列表以及激活的列表中。该语句需要一个条件,如果用户也有激活的服务计划,它将从查询中排除用户。现在,我有一些用户落入了不应该在那里的停用用户。
无论如何,提前谢谢你!
答案 0 :(得分:2)
您可以使用not exits()
重写您的查询,如@GarethD建议的那样。
如果不能很好地扩展,另一种方法可能是一个group by子句,例如:
SELECT u.*
FROM users u
LEFT JOIN services s ON s.assignedto=u.id
GROUP BY u.id
HAVING max(s.status) <> 1
但是,最好的选择是额外的领域。如果您向status
添加users
字段,则可以直接对其进行索引和查询。您可以使用触发器维护它,但就个人而言,这是一种罕见的情况,我发现在应用程序中维护它是一种更好的方法。 (基本上,您永远不知道何时需要快速将用户标记为非活动状态而不会弄乱其他数据库表。)
答案 1 :(得分:0)
您可以使用NOT EXISTS
排除使用有效服务的用户:
SELECT u.*
FROM users u
WHERE NOT EXISTS
( SELECT 1
FROM Services s
WHERE s.assignedto=u.id
AND s.status = 1
);
为了获得你想要的数量,我认为你需要这样的东西:
SELECT COUNT(CASE WHEN s.ActiveServices > 0 THEN 1 END) AS ActiveUsers,
COUNT(CASE WHEN s.ActiveServices = 0 THEN 1 END) AS DeactivatedUsers,
COUNT(CASE WHEN s.assignedto IS NULL THEN 1 END) AS OtherUsers
FROM users u
LEFT JOIN
( SELECT s.assignedto,
COUNT(CASE WHEN s.status = 1 THEN 1 END) AS ActiveServices
FROM Services s
GROUP BY s.assignedto
) s
ON s.assignedto = u.ID
我刚刚记得MySQL中的NOT EXISTS is not as efficient as LEFT JOIN/IS NULL,Denis也指出NOT EXISTS不能很好地扩展。 LEFT JOIN方法将是:
SELECT u.*
FROM Users u
LEFT JOIN Services s
ON s.assignedto = u.id
AND s.status = 1
WHERE s.assignedto IS NULL;