MySQL GROUP BY для поиска дубликатов с предложением where - PullRequest
1 голос
/ 21 сентября 2019

Сейчас у меня есть:

custom_id| field_id | value
-------------------------
 20987   | 72       | No mark
 20987   | 122      | None
 20987   | 126      | http
 20999   | 72       | No mark
 20999   | 122      | 100
 20999   | 126      | http

Мне нужно найти custom_id, который соответствует трем предложениям.Первый - field_id = 72 и value = «Нет отметки».Второе - field_id = 122 и значение = '' .Third - field_id = 126 и значение типа '% http%'.

Я выполняю этот запрос:

SELECT custom_id, value, field_id, count(custom_id) 
WHERE(field_id = '72' AND value = 'No mark') 
OR (field_id = '126' AND value like '%http%') 
OR (field_id = '122' AND value ='') 
GROUP BY custom_id
HAVING count(custom_id)=3 
LIMIT 10000

И у меня был результат:

[(20987,72,'No mark',3)]

Как мне упорядочить или отсортировать значения в 'group by / count'предложение, чтобы иметь результат как:

[(20987,126,'http',3)]

Ответы [ 2 ]

0 голосов
/ 21 сентября 2019

В MySQL 8.0 вы можете использовать оконные функции для решения этой проблемы.Во-первых, отфильтруйте записи, соответствующие 3 условиям, выполняя подсчет окон и назначая условный ранг, который ставит значение 'http' на первое место.Затем внешний запрос фильтрует записи, количество окон в которых равно 3 и которые занимают первое место:

SELECT custom_id, value, field_id, cnt
FROM (
    SELECT 
        t.*, 
        ROW_NUMBER() OVER(PARTITION BY custom_id ORDER BY value LIKE '%http%') rn,
        COUNT(*) OVER (PARTITION BY custom_id) cnt
    FROM mytable t
    WHERE 
           (field_id = '72' AND value = 'No mark') 
        OR (field_id = '126' AND value like '%http%') 
        OR (field_id = '122' AND value ='') 
) x
WHERE cnt = 3 AND rn = 1
LIMIT 10000

Примечание: на основе данных примера лучше будет написать value LIKE '%http%' value = 'http'.

Демонстрация на БД Fiddle :

| custom_id | value | field_id | cnt |
| --------- | ----- | -------- | --- |
| 20987     | http  | 126      | 3   |

В более ранних версиях, когда оконные функции недоступны, вы можете выполнить агрегированиев подзапросе для создания списка custom_id s, которые удовлетворяют условиям, а затем JOIN результатов с исходной таблицей при фильтрации по записи, которая имеет ожидаемый value:

SELECT t.*
FROM mytable t
INNER JOIN (
    SELECT custom_id
    FROM mytable
    WHERE
            (field_id = '72' AND value = 'No mark') 
        OR (field_id = '126' AND value like '%http%') 
        OR (field_id = '122' AND value ='') 
    GROUP BY custom_id
    HAVING count(custom_id)=3 
) x ON x.custom_id = t.custom_id
WHERE t.value like '%http%'

Демонстрация на DB Fiddle (те же результаты, что и выше).

0 голосов
/ 21 сентября 2019

, если вы хотите получить custom_id, соответствующий условию
Вы можете использовать некоторое самостоятельное соединение для таблицы

SELECT a.custom_id
FROM my_table a
INNER JOIN my_tbale b  ON a.custom_id = b.custom_id 
  AND a.field_id = '72' 
    AND a.value = 'No mark'
INNER JOIN JOIN my_tbale c  ON a.custom_id = c.custom_id 
  AND b.field_id = '126' 
    AND b.value like '%http%'
WHERE a.field_id = '122' 
  AND a.value =''
...