MySQL - выбрать строки, где значение столбца только 0, группировать по другому столбцу? - PullRequest
0 голосов
/ 13 сентября 2018

Пример таблицы:

ID, foreign_id, status

ID является уникальным , foreign_id - нет.Пример строки:

1, 1111, 0  
2, 2222, 0  
3, 3333, 1
4, 1111, 1
5, 4444, 0

То, что я хочу выбрать, является уникальным foreign_id, которые имеют статус только 0. Если он имеет статус 0, но другая строка с тем же внешним идентификатором имеет статускак 1, не выбирайте это foreign_id.Ожидаемый результат:

1, 2222, 0
5, 4444, 0

Я могу выбрать, где status = 0 и сгруппировать по foreign_id, но это просто выберет строку, где статус равен 0, хотя может быть другая строка с таким же foreign_idи статус 1.

SELECT ID, foreign_id 
FROM table 
WHERE status = 0 
GROUP BY foreign_id

Любая помощь приветствуется.

Ответы [ 5 ]

0 голосов
/ 13 сентября 2018

Как уже говорили другие, вы должны агрегировать данные, но есть много потенциальных проблем с этим. Но прежде чем мы перейдем к этому, вы заявили, что хотите получить исходные записи в выходных данных, а не консолидированные данные, и самое простое решение - использовать 2 запроса - один для идентификации foreign_ids только с status = 0 и один для получения соответствующего строки

SELECT r.*
FROM examples r
JOIN ( SELECT s.foreign_id, MAX(s.status)
  FROM examples s
  GROUP BY s.foreign_id
  HAVING MAX(s.status)=0
) t
ON r.foreign_id=t.foreign_id

В качестве альтернативы вы можете получить foreign_ids, где status! = 0, и исключить их во втором запросе, что может быть более эффективным в зависимости от распределения ваших данных.

Если это не так, то в случае, когда «status» <0. Вывод будет включать эти строки (потенциально то же самое может произойти с SUM ()). Есть несколько способов решения этой проблемы, например, SUM (ABS (статус)) или SUM (IF (статус = 0,0,1)). Как предполагает Мадхур, вы также можете использовать GROUP_CONCAT (статус) и проверять, что выходной столбец только «0». </p>

Но я подозреваю, что вы собираетесь сказать мне, что статус не может быть отрицательным (или нулевым?), Поскольку это номинальное число . Если это так, то вы используете неправильный тип данных - вы должны использовать ENUM. Если это так, то вы не можете применить SUM () или MAX () к ENUM, но вы все равно можете использовать методы SUM (IF (status = ?, 0,1)) или GROUP_CONCAT ().

Следовательно ....

SELECT r.*
FROM examples r
JOIN ( SELECT s.foreign_id, SUM(IF(status=0,0,1))
  FROM examples s
  GROUP BY s.foreign_id
  HAVING SUM(IF(status=0,0,1))=0
) t
ON r.foreign_id=t.foreign_id
0 голосов
/ 13 сентября 2018

(я отредактировал это, чтобы продемонстрировать, что это работает, и прояснить некоторые вещи):

Возможно, вас заинтересует утверждение HAVING.

Вы можете использовать оператор HAVING после вашего GROUP BY.Вот довольно хорошее объяснение: https://www.dofactory.com/sql/having

Короче говоря, оператор HAVING позволяет фильтровать данные, которые возвращаются в результате выражения GROUP BY.

Tryэто:

SELECT 
     foreign_id, MAX(status) AS status
FROM
     myTable
GROUP BY 
     foreign_id
HAVING 
     MAX(status) = 0

Вот пример его работы (проверено в базовом файле MS Access):enter image description here

Затем я ввел этот код:enter image description here

И я получил эти результаты:enter image description here

Дайте мне знать, если у вас есть какие-либо вопросы!

0 голосов
/ 13 сентября 2018

Вы можете использовать group by и having:

select foreign_id, max(status) as status
from t
group by foreign_id
having max(status) = 0;

Как правило, вам нужно сделать тест после group by.

Если вам нужны полные строки, используйте not exists:

select t.*
from t
where not exists (select 1
                  from t t2
                  where t2.foreign_id = t.foreign_id and t2.status <> 0
                 );
0 голосов
/ 13 сентября 2018

использовать агрегатную функцию

select * from t where foreign_id in (
     select foreign_id
        from t
        group by foreign_id
        having min(status) = 0
       ) and status!=1
0 голосов
/ 13 сентября 2018

Используя GROUP_CONCAT и DISTINCT, мы группируем все уникальные статусы против foreign_id. Теперь внутри предложения HAVING нам просто нужно отфильтровать только те foreign_id, где уникальные статусы только '0'.

Попробуйте следующее:

SELECT ID, foreign_id, status, GROUP_CONCAT(DISTINCT status) as statuses 
FROM table 
GROUP BY foreign_id 
HAVING statuses = '0'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...