2013-11-25 7 views
0

Постараюсь быть прямо в точку, что я пытаюсь сделать здесь ...MySQL: Условный оператор в запросе

У меня есть запрос, который работает, но недавно я обнаружил проблему с ним. Теперь я могу просто исправить это с помощью PHP, но я знаю, что это может быть сделано каким-то образом в MySQL ... Я просто не знаю, как это сделать. Так вот что происходит:

У меня есть таблица USERS и таблица УСЛУГ. Пользователь может иметь несколько сервисов (каждая служба полностью независима друг от друга), и каждая служба имеет поле «статус». Состояние определяет текущее состояние службы: active/inactive

Запрос вызывается, когда вы переходите на страницу «Управление пользователями», где каждый пользователь разбит на категорию, к которой он принадлежит. Для этого примера это будут: Активные пользователи | Деактивированные пользователи | Другие пользователи (пользователи без какого-либо плана обслуживания вообще).

Так что мой деактивируется пользователи запрос сводится к следующему:

SELECT DISTINCT u.* FROM users u LEFT JOIN services s ON s.assignedto=u.id WHERE s.status!=1 

Оператор прекрасно работает, однако, если у клиента есть 2 планы услуг, где один активируется и один деактивирован, то он будет отображаться в деактивированный список, а также активированный список. Оператору требуется условие, при котором пользователь будет исключать пользователя из запроса, если они ТАКЖЕ имеют активированный план обслуживания. Сейчас у меня есть несколько пользователей, которые попадают в дезактивированных пользователей, которых там не должно быть.

В любом случае, спасибо заранее!

ответ

2

Вы можете переписать запрос с not exits() как предложено @GarethD.

Другой подход, чтобы иметь в виду, если он не очень хорошо масштабируется может быть группа по статье, например .:

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, вы можете напрямую его индексировать и запрашивать. Вы можете сохранить его с помощью триггера, но, говоря лично, это редкий случай, когда я обнаружил, что его поддержание в приложении - лучший подход. (В принципе, вы никогда не знаете, когда вам нужно быстро пометить пользователя как неактивного, не вмешиваясь в другие таблицы БД.)

+0

+1 для группы. –

+0

Удивительный. Да, я думал об этом подходе первоначально, но полагаясь на поле, чтобы определить бездействие пользователя (я чувствую) в какой-то момент настраивается на неудачу. В любом случае, когда услуга деактивируется (неудачные платежи, ручная деактивация и т. Д.), Я должен отметить это поле для деактивации. Хотя этот SQL-запрос решает все :). Спасибо! – user0000001

+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 

I только что вспомнили, что NOT EXISTS is not as efficient as LEFT JOIN/IS NULL в MySQL, Денис также указал, что 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; 
Смежные вопросы