SQL-запрос для эффективного выбора неидеальных дубликатов - PullRequest
0 голосов
/ 09 мая 2018

У меня есть таблица базы данных в формате значения атрибута сущности, которая выглядит следующим образом:

radiology table

Я хочу выбрать все строки, которые имеют одинаковые значения для столбцов «сущность» и «атрибут», но имеют разные значения для столбца «значение». Несколько строк с одинаковыми значениями для всех трех столбцов должны рассматриваться как одна строка. Я достиг этого, используя SELECT DISTINCT.

SELECT entity_id, attribute_name, COUNT(attribute_name) AS NumOcc 
FROM (SELECT DISTINCT * FROM radiology) x 
GROUP BY entity_id,attribute_name 
HAVING COUNT(attribute_name) > 1

Ответ на этот запрос

Однако я прочитал, что использование SELECT DISTINCT довольно дорого. Я планирую использовать этот запрос для очень больших таблиц, я ищу способ оптимизировать этот запрос, возможно, без использования SELECT DISTINCT.

Я использую PostgreSQL 10.3

Ответы [ 3 ]

0 голосов
/ 09 мая 2018

Это должно работать для вас:

select a.* from radiology a join 
(select entity, attribute, count(distinct value) cnt
from radiology 
group by entity, attribute
having count(distinct value)>1)b
on a.entity=b.entity and a.attribute=b.attribute
0 голосов
/ 09 мая 2018

Я хочу выбрать все строки, которые имеют одинаковые значения для столбцов «сущность» и «атрибут», но имеют разные значения для столбца «значение».

Ваш метод этого не делает. Я бы подумал exists:

select r.*
from radiology r
where exists (select 1
              from radiology r2
              where r2.entity = r.entity and r2.attribute = r.attribute and
                    r2.value <> r.value
             );

Если вы просто хотите, чтобы значения сущности / атрибута были указаны парами, используйте group by:

select entity, attribute
from radiology
group by entity, attribute
having min(value) <> max(value);

Обратите внимание, что вы могли бы использовать having count(distinct value) > 1, но count(distinct) влечет за собой больше накладных расходов, чем min() и max().

0 голосов
/ 09 мая 2018
select  *
from    radiology r
join    (
        select  entity_id
        ,       attribute_name
        from    radiology
        group by
                entity_id
        ,       attribute_name
        having  count(distinct value) > 1
        ) dupe
 on     r.entity_id = dupe.entity_id
        and r.attribute_name = dupe.attribute_name
...