[英]MySQL: Conditional statement within query
I'll try to be straight to the point of what I am trying to accomplish here... 我会尽力直截了当地说明我要在这里完成的事情......
I have a query that works but I have recently discovered an issue with it. 我有一个有效的查询,但我最近发现了它的问题。 Now, I could simply fix this with PHP but I know it can be done somehow in MySQL... I just don't know how. 现在,我可以简单地用PHP修复它,但我知道它可以在MySQL中以某种方式完成...我只是不知道如何。 So this is what is going on: 所以这是正在发生的事情:
I have a USERS table and a SERVICES table. 我有一个USERS表和一个SERVICES表。 A user can have multiple SERVICES (each service being completely independent from one another) and every service has a field called "status". 用户可以拥有多个服务(每个服务彼此完全独立),并且每个服务都有一个名为“status”的字段。 Status defines the current state the service is in: active / inactive 状态定义服务所处的当前状态:活动/非活动
The query is called when you go to the Manage Users page, where every user is split into the category it belongs. 当您转到“管理用户”页面时,将调用该查询,其中每个用户都将拆分为其所属的类别。 For this example, it will be: Active Users | 对于此示例,它将是:活动用户| Deactivated Users | 已停用的用户| Other Users (users without any service plan at all). 其他用户(完全没有任何服务计划的用户)。
So my deactivated users query comes down to this: 所以我的停用用户查询归结为:
SELECT DISTINCT u.* FROM users u LEFT JOIN services s ON s.assignedto=u.id WHERE s.status!=1
The statement works great, however, if the customer has 2 services plans where one is activated and one is deactivated, then he will appear in the deactivated list as well as the activated list. 该声明效果很好,但是,如果客户有2个服务计划,其中一个被激活而另一个被停用,那么他将出现在已停用的列表以及激活的列表中。 The statement needs a condition where it will exclude the user from the query if they ALSO have an activated service plan. 该语句需要一个条件,如果用户也有激活的服务计划,它将从查询中排除用户。 Right now, I have a few users that are falling into the deactivated users that should not be there. 现在,我有一些用户落入了不应该在那里的停用用户。
Anyway, thank you in advance! 无论如何,提前谢谢你!
You could rewrite your query with not exits()
as @GarethD suggested. 你可以用@GarethD建议的not exits()
重写你的查询。
Another approach to have in mind if it doesn't scale well could be a group by clause, eg: 如果不能很好地扩展,另一种方法可能是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
The best option, though, would be an extra field. 不过,最好的选择是额外的领域。 If you add a status
field to users
, you could index and query that directly. 如果向users
添加status
字段,则可以直接索引和查询。 You could maintain it using a trigger but, speaking personally, this is a rare case where I've found that maintaining it in the app is a better approach. 您可以使用触发器维护它,但就个人而言,这是一种罕见的情况,我发现在应用程序中维护它是一种更好的方法。 (Basically, you never know when you need to quickly mark a user as inactive without messing around with other DB tables.) (基本上,您永远不知道何时需要将用户快速标记为非活动状态而不会弄乱其他数据库表。)
You can exclude users with active services using NOT EXISTS
: 您可以使用NOT EXISTS
排除具有活动服务的用户:
SELECT u.*
FROM users u
WHERE NOT EXISTS
( SELECT 1
FROM Services s
WHERE s.assignedto=u.id
AND s.status = 1
);
To get the counts you are after I think you need something like this: 为了获得你想要的计数,我认为你需要这样的东西:
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
I have just remembered that NOT EXISTS is not as efficient as LEFT JOIN/IS NULL in MySQL, Denis has also pointed out that NOT EXISTS does not scale well. 我刚才记得NOT EXISTS不如 MySQL中的LEFT JOIN / IS NULL效率高 ,Denis也指出NOT EXISTS不能很好地扩展。 The LEFT JOIN Approach would be: 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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.