Поиск дубликатов в SQL на основе условий предложения OR - PullRequest
0 голосов
/ 05 февраля 2019

Возьмите воображаемую схему, представляющую продукты в MySQL v5.6.41 db:

 ------------------------------------------------
| id | name | vendor_id | vendor_sku | upc | ean |
|----|------|-----------|------------|-----|-----|
| 1  | AAAA | 2         | 5678       | 456 | 111 | [1]
| 2  | aaaa | 2         | 7878       | 789 | 222 | [1]
| 3  | bbbb | 2         | 1234       | 111 | 333 | [2]
| 4  | cccc | 2         | 1234       | 222 | 444 | [2]
| 5  | dddd | 2         | 1111       | 123 | 555 | [3]
| 6  | eeee | 2         | 2222       | 123 | 666 | [3]
| 7  | ffff | 2         | 3333       | 333 | 777 | [4]
| 8  | gggg | 2         | 4444       | 444 | 777 | [4]
| 9  | hhhh | 2         | 5555       | 555 | 888 |
| 10 | iiii | 2         | 6666       | 666 | 999 |
| 11 | jjjj | 2         | 7777       | 777 | 000 |
| 12 | kkkk | 2         | 8888       | 888 | 001 |
| 13 | llll | 2         | 9999       | 999 | 002 |
| 14 | mmmm | 2         | 0000       | 000 | 003 | 
------------------------------------------------

Я пытаюсь найти количество повторяющихся строк, которые соответствуют одному из следующих критериев:

  1. То же vendor_id и то же vendor_sku ИЛИ
  2. То же vendor_id и то же name (без учета регистра) ИЛИ
  3. То же vendor_id и то же upc ИЛИ
  4. То же vendor_id и то же ean

(обозначение [n] рядом с каждымстрока будет соответствовать условию, в котором эти строки являются дубликатами)

Я уже собрал этот запрос, но он будет соответствовать только условию # 1:

SELECT
    count(*)
FROM
    my_table
GROUP BY
    vendor_id, vendor_sku
HAVING 
    COUNT(*) > 1

И мой ожидаемый результат будетбыть 8 на основе этого примера

Ответы [ 2 ]

0 голосов
/ 05 февраля 2019

Я все еще думаю, что есть возможные варианты сделать это без использования зависимого подзапроса.Когда мне удавалось избавиться от зависимого подзапроса, план выполнения обычно становился лучше.

Итак:

SELECT
      COUNT(DISTINCT t1.id)
FROM
    my_table AS t1
    INNER JOIN my_table AS t2 ON (
            t1.vendor_id = t2.vendor_id
        AND t1.id != t2.id
        AND (
               t1.vendor_sku = t2.vendor_sku
            OR t1.name = t2.name
            OR t1.upc = t2.upc
            OR t1.ean = t2.ean
        )
    )

ИЛИ:

SELECT
      COUNT(DISTINCT t1.id)
FROM
    my_table AS t1
    LEFT JOIN my_table AS t2 ON (
            t1.vendor_id = t2.vendor_id
        AND t1.id != t2.id
        AND (
               t1.vendor_sku = t2.vendor_sku
            OR t1.name = t2.name
            OR t1.upc = t2.upc
            OR t1.ean = t2.ean
        )
    )
WHERE
    t2.id IS NOT NULL

PS Я не сталесть время, чтобы исправить мой предыдущий ответ, когда указал на ошибку, поэтому я использовал del tag вместо удаления ответа (извините за это).Позже я хотел это исправить, но ответ был удален модератором.

0 голосов
/ 05 февраля 2019

Я думаю, exists может работать:

select count(*)
from my_table t
where exists (select 1
              from my_table t2
              where t2.vendor_id = t.vendor_id and
                    t2.id <> t.id and
                    (t2.vendor_sku = t.vendor_sku or
                     t2.name = t.name or
                     t2.upc = t.upc or
                     t2.ean = t.ean
                    )
             );

Обратите внимание, что чувствительность к регистру зависит от вашего сопоставления.Я не добавил явной обработки для случая (я бы просто использовал lower()), потому что не ясно, нужна ли такая обработка.

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