MySQL GROUP для столбца на основе другого столбца, но также исключают дубликаты на основе второго столбца - PullRequest
0 голосов
/ 08 февраля 2020

У меня есть эта база данных

+----+-------+--------+-------------+---------------------+------------+---------+
| id | jobid | status | worker      | addedTime           | jobType    | sceneId |
+----+-------+--------+-------------+---------------------+------------+---------+
| 56 | TEST1 |      2 | na          | 2020-02-07 13:19:28 | PROC_STD   | 123test |
| 57 | TEST2 |      2 | na          | 2020-02-07 13:19:29 | PROC_STD   | 123test |
| 58 | TEST3 |     -1 | na          | 2020-02-08 06:45:25 | PROC_STD   | 124test |
| 59 | TEST4 |     -1 | na          | 2020-02-08 06:45:25 | PROC_STD   | 124test |
| 60 | TEST5 |      2 | na          | 2020-02-08 06:55:24 | PROC_STD   | 124test |
| 61 | TEST6 |      2 | na          | 2020-02-08 06:55:25 | PROC_STD   | 124test |
+----+-------+--------+-------------+---------------------+------------+---------+

Использование

SELECT sceneId, COUNT(*) FROM jobqueue WHERE status=2 GROUP BY sceneId, status HAVING COUNT(*) > 1;

Я могу сгруппировать sceneId, чтобы получить это

+---------+----------+
| sceneId | COUNT(*) |
+---------+----------+
| 123test |        2 |
| 124test |        2 |
+---------+----------+

Но меня интересует только sceneId 123test, поскольку все строки имеют статус 2, тогда как 124test имеет статус 2 и -1.

Изменение запроса следующим образом status! = 2 Я могу хотя бы получить sceneId. Я не хочу, чтобы

SELECT sceneId, COUNT(*) FROM jobqueue WHERE status!=2 GROUP BY sceneId, status HAVING COUNT(*) > 1;

получил это

+---------+----------+
| sceneId | COUNT(*) |
+---------+----------+
| 124test |        2 |
+---------+----------+

Может ли мой первый запрос быть отфильтрован вторым отрицательным запросом, или есть другие хитрые приемы для этого i sql?

Для ясности я хочу изменить свой запрос, чтобы получить только sceneIds (может быть больше одного, но в моем примере есть только один действительный результат, который я хочу), который имеет только статус 2, это результат, который я хочу?

+---------+----------+
| sceneId | COUNT(*) |
+---------+----------+
| 123test |        2 |
+---------+----------+

Я использую mysql Ver 14.14 Distrib 5.7.28, для Linux (x86_64) используя оболочку EditLine в Ubuntu 16.04

Ответы [ 3 ]

1 голос
/ 08 февраля 2020

Да, вы можете достичь желаемых результатов, используя исключение JOIN.

Пример: DB Fiddle

SELECT j1.sceneId, COUNT(j1.id) AS dupes
FROM jobqueue AS j1
LEFT JOIN jobqueue AS j2
ON j1.sceneId = j2.sceneId
AND j2.status != 2
WHERE j2.id IS NULL
GROUP BY sceneid
HAVING dupes > 1;

Результат:

| sceneid | dupes |
| ------- | ----- |
| 123test | 2     |

Это работает путем исключения любых записей, которые сопоставляются в таблице JOIN с записями в таблице FROM с теми же sceneId, которые также имеют status, отличный от 2.

1 голос
/ 08 февраля 2020

Проблема в том, что, помещая условие в status в предложении where, вы удаляете строки, прежде чем сможете проверить их содержимое. Вместо этого вы можете фильтровать с другим условием having, которое выполняет условное агрегирование:

select sceneid, count(*) 
from jobqueue 
group by sceneid 
having count(*) > 1 and min(status = 2) = 1

. Это дает вам список sceneid с, которые встречаются более одного раза и все строки которых имеют status = 2.

0 голосов
/ 08 февраля 2020

Вы можете использовать комбинацию group_concat и подзапрос, чтобы получить желаемый результат. Как то так

SELECT temp.sceneId, 
       temp.count 
FROM   (SELECT   sceneId, 
                 COUNT(*) AS COUNT, 
                 GROUP_CONCAT(DISTINCT(STATUS)) AS status_filter 
        FROM     jobqueue 
        GROUP BY sceneId ) AS temp 
WHERE   temp.status_filter = 2
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...