Удаление дублирующихся строк в сложном MySQL Query - не уверен, что я делаю это неправильно, или это ошибка MySQL - PullRequest
0 голосов
/ 24 ноября 2011

У меня достаточно сложный запрос MySQL, выполняемый в базе данных другого разработчика. Я пытаюсь скопировать его данные в нашу новую структуру базы данных, поэтому я выполняю этот запрос, чтобы передать данные для копирования. Основная таблица содержит около 45 000 строк.

Как видно из запроса ниже, есть много полей из нескольких разных таблиц. Моя проблема в том, что поле Ref.refno (как ref_id) проходит, в некоторых случаях, два или три раза. Это потому, что в таблице LandlordOnlineRef (LLRef) иногда есть несколько строк с одним и тем же ссылочным номером - в данном случае, потому что строка должна была быть отредактирована, но вместо этого была продублирована ...

Вот что я пытался сделать: -

  1. SELECT DISTINCT(Ref.refno) [...] - это никак не влияет на вывод, хотя я бы предположил, что он остановит выбор дубликатов refno ID
  2. Это ошибка MySQL или я? - я также попытался добавить GROUP BY ref_id в конец моего запроса. Обычно выполнение запроса занимает несколько миллисекунд, но когда я добавляю GROUP BY в конец, он, кажется, выполняется бесконечно - я ждал несколько минут, но ничего не происходило. Я подумал, что это может быть трудно, потому что я использую LIMIT 1000, поэтому я также попытался LIMIT 10, но все равно получил тот же эффект.

Вот запрос проблемы - спасибо!

SELECT 

    -- progress
    Ref.refno                   AS ref_id,
    Ref.tenantid                AS tenant_id,
    Ref.productid               AS product_id,
    Ref.guarantorid             AS guarantor_id,
    Ref.agentid                 AS agent_id,
    Ref.companyid               AS company_id,
    Ref.status                  AS status,
    Ref.startdate               AS ref_start_date,
    Ref.enddate                 AS ref_end_date,

    -- ReferenceDetails
    RefDetails.creditscore      AS credit_score,

    -- LandlordOnlineRef
    LLRef.propaddress           AS prev_ll_address,
    LLRef.rent                  AS prev_ll_rent,
    LLRef.startdate             AS prev_ll_start_date,
    LLRef.enddate               AS prev_ll_end_date,
    LLRef.arrears               AS prev_ll_arrears,
    LLRef.arrearsreason         AS prev_ll_arrears_reason,
    LLRef.propertycondition     AS prev_ll_property_condition,
    LLRef.conditionreason       AS prev_ll_condition_reason,
    LLRef.consideragain         AS prev_ll_consider_again,
    LLRef.completedby           AS prev_ll_completed_by,
    LLRef.contactno             AS prev_ll_contact_no,
    LLRef.landlordagent         AS prev_ll_or_agent,

    -- EmpDetails
    EmpRef.cempname             AS emp_name,
    EmpRef.cempadd1             AS emp_address_1,
    EmpRef.cempadd2             AS emp_address_2,
    EmpRef.cemptown             AS emp_address_town,
    EmpRef.cempcounty           AS emp_address_county,
    EmpRef.cemppostcode         AS emp_address_postcode,
    EmpRef.ctelephone           AS emp_telephone,
    EmpRef.cemail               AS emp_email,
    EmpRef.ccontact             AS emp_contact,
    EmpRef.cgross               AS emp_income,
    EmpRef.cyears               AS emp_years,
    EmpRef.cmonths              AS emp_months,
    EmpRef.cposition            AS emp_position,

    -- EmpLlodReference
    ELRef.lod_ref_status        AS prev_ll_status,
    ELRef.lod_ref_email         AS prev_ll_email,
    ELRef.lod_ref_tele          AS prev_ll_telephone,
    ELRef.emp_ref_status        AS emp_status,
    ELRef.emp_ref_tele          AS emp_telephone,
    ELRef.emp_ref_email         AS emp_email

FROM ReferenceDetails AS RefDetails

LEFT JOIN progress          AS Ref      ON Ref.refno
LEFT JOIN LandlordOnlineRef AS LLRef    ON LLRef.refno = Ref.refno
LEFT JOIN EmpLlodReference  AS ELRef    ON ELRef.refno = Ref.refno
LEFT JOIN EmpDetails        AS EmpRef   ON EmpRef.tenantid = Ref.tenantid

-- For testing purposes to speed things up, limit it to 1000 rows
LIMIT 1000

Ответы [ 3 ]

1 голос
/ 24 ноября 2011
LEFT JOIN progress          AS Ref      ON Ref.refno

собирается превратить это в декартово соединение.Вы не проводите явное сравнение, вы говорите «объединить все записи, где есть ненулевое значение».

Разве это не должно быть

LEFT JOIN progress          AS Ref      ON Ref.refno = RefDetails.something

?

1 голос
/ 24 ноября 2011
  1. Поместите все выбранные столбцы в DISTINCT, разделив их ,.Если вы хотите сохранить переименование, добавьте еще один SELECT DISTINCT(*) FROM (YOUR_SELECT).

  2. Есть ли индексы для столбцов в предложении GROUP BY?LIMIT применяется после GROUP BY.Таким образом, ограничение не влияет на время выполнения запроса.

0 голосов
/ 24 ноября 2011

Общее правило - никогда не группировать больше столбцов, чем нужно.Используйте подзапрос с группой по таблице, которая возвращает дублирующиеся строки, чтобы избавиться от них.

Измените:

LEFT JOIN LandlordOnlineRef AS LLRef    ON LLRef.refno = Ref.refno

на:

Left Join (select refno
, othercolumns you need 
from LandlordOnlineRef 
group by refno,othercolumn) as LLRef

Не уверенв какие столбцы вы хотите включить сюда, но на любом уровне таблицы вы можете изменить эту таблицу на подзапрос, чтобы исключить повторяющиеся строки перед объединением.Как говорит MarkBannister, вам понадобится некоторая логика для определения уникального refno в LLRef.Вы также можете использовать столбец даты для «самой последней» или любую другую логику, о которой вы можете подумать, чтобы получить уникальный LLRef и информацию, относящуюся к этой записи.,га

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