Удалить дубликаты в наборе результатов SQL ОДНОЙ таблицы

День/Вечер все,

Я ищу последние штрихи к приведенному ниже запросу. Мне нужно удалить повторяющиеся вхождения столбца в определенной строке. В настоящее время используется приведенный ниже SQL:

SELECT CBNEW.*
FROM CallbackNewID CBNEW 
INNER JOIN (SELECT IDNEW, MAX(CallbackDate) AS MaxDate 
FROM CallbackNewID 
GROUP BY IDNEW) AS groupedCBNEW 
ON (CBNEW.CallbackDate = groupedCBNEW.MaxDate) AND (CBNEW.IDNEW = groupedCBNEW.IDNEW);

Мой набор результатов выглядит следующим образом

ID     RecID  Comp  Rem Date_               IDNEW   IDOLD   CB? CallbackDate
138618  83209   1   0   2012-03-16 12:40:00 83209   83209   2   16-Mar-12
138619  83209   1   0   2012-03-16 12:40:00 83209   83209   2   16-Mar-12
110470  83799   1   0   2011-07-27 11:46:00 83799   83799   10  27-Jul-11
110471  83799   1   0   2011-07-27 11:46:00 83799   83799   10  27-Jul-11

Однако это дает мне повторяющиеся значения в столбцах CallBackDate и IDNEW, потому что в таблице есть несколько разных первичных ключей с одинаковыми значениями IDNEW и CallbackDate.

Если я выгружу этот результат в Excel, я могу просто удалить дубликаты в первом столбце идентификатора, и проблема будет решена.

Но я хочу убедиться, что мой результат включает только ПЕРВЫЙ экземпляр столбца ID, где дублируются IDNEW и CallbackDate.

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

Ваша помощь очень ценится.


person Jof Davies    schedule 04.11.2013    source источник


Ответы (4)


Попробуйте добавить MIN(ID) во внутренний запрос, а затем добавить его также в предложение ON:

SELECT CBNEW.*
FROM CallbackNewID CBNEW 
INNER JOIN (SELECT IDNEW, MIN(ID) AS MinId, MAX(CallbackDate) AS MaxDate 
FROM CallbackNewID 
GROUP BY IDNEW) AS groupedCBNEW 
ON (CBNEW.CallbackDate = groupedCBNEW.MaxDate) 
   AND (CBNEW.IDNEW = groupedCBNEW.IDNEW)
   AND (CBNEW.ID = groupedCBNEW.MinId) ;

демонстрация sqlfiddle

person Filipe Silva    schedule 04.11.2013
comment
Я не понимаю, почему вам нужно мин, чтобы удалить дубликаты? - person DevelopmentIsMyPassion; 04.11.2013
comment
он попросил первый идентификатор группы, которую он делает с IDNEW. Я думал о MIN, чтобы сделать это. Как вы думаете, это неправильно? - person Filipe Silva; 04.11.2013
comment
Да, я так думаю, если только он не считает, что результат вашего запроса правильный - person DevelopmentIsMyPassion; 04.11.2013
comment
Можете ли вы уточнить, почему вы считаете, что это неправильно? Вывод, безусловно, кажется мне правильным, если вы посмотрите на результаты sqlfiddle и образцы данных, которые у него есть по его вопросу. - person Filipe Silva; 04.11.2013
comment
К сожалению, это дает мне только 4 411 записей, а не 11 337 результатов, которые я ожидаю. Используя исходный SQL, я получаю 11 364 результата. Дамп в Excel, 43 Dupes для удаления. Не уверен, какое значение будет равно 4411, но я предполагаю, что это как-то связано с оператором MIN. - person Jof Davies; 04.11.2013
comment
Я не уверен, как это происходит. Если вы сгруппируете по idNEW и получите max(callbackdate) и min(id) для этих элементов, вы должны получить правильное количество записей. можете ли вы добавить еще несколько примеров в sqlfiddle и поделиться ими в своем вопросе, чтобы увидеть, что не так в запросе? - person Filipe Silva; 04.11.2013
comment
На самом деле, я предполагаю, что я ищу максимальное уникальное значение дат в наборе из 50 000. 4411 записей, вероятно, означают, что в наборе всего 4411 уникальных записей. - person Jof Davies; 04.11.2013
comment
Разве это не то, что вы ищете? - person Filipe Silva; 04.11.2013
comment
Я не боюсь. Я добавил немного больше в скрипку sqlfiddle.com/#!3/f1ce6/ 1/0 Новые 3 записи появляются в результатах скрипки, но они не отображаются в моем наборе результатов MS Access. - person Jof Davies; 04.11.2013
comment
Я не понимаю, почему они не должны появляться. Вы видите какую-то причину? - person Filipe Silva; 04.11.2013
comment
Я полностью сбит с толку, я пытаюсь определить, откуда он получает неверный счет 4411, и я не могу найти это число, возясь с набором в Excel, подсчитывая дубликаты во всех столбцах ячеек. - person Jof Davies; 05.11.2013
comment
В Excel немного сложно удалить дубликаты на основе столбцов дерева (id, newid и date). Если вы удалите дубликаты на основе только одного столбца, вы можете получить больше вещей, чем вам нужно. - person Filipe Silva; 05.11.2013
comment
Я на 100% уверен в количестве записей, которые я ожидаю увидеть. Когда я смотрю на это, кажется, что у временной таблицы «groupedCBNEW» есть проблема. В нем всего 4411 записей. Я что-то упускаю, когда прошу создать его в SQL? - person Jof Davies; 05.11.2013
comment
Кроме того, если я создам простой запрос, подобный этому: 'code' SELECT Min(CBNEW.ID) AS MinOfID, CBNEW.IDNEW, Max(CBNEW.CallbackDate) AS MaxOfCallbackDate FROM CallbackNewID AS CBNEW GROUP BY CBNEW.IDNEW; Тогда я получаю именно те результаты, которые мне нужны, хотя и без дополнительных полей. - person Jof Davies; 05.11.2013
comment
Вы правы, это очень странно. Если вы выполняете внутреннее соединение с подмножеством, оно должно дать вам это подмножество, не меньше этого. Я действительно не могу понять, как это может дать вам меньше результатов. Прости. - person Filipe Silva; 05.11.2013
comment
Я думал, что вы его привязали, поэтому я удалил свой ответ. Я только что восстановил его на случай, если @user2953562 может счесть его полезным. В любом случае, вы можете сохранить мой голос.... ;) - person Gord Thompson; 05.11.2013

Вот довольно "грубый силовой" подход. Он просто берет результаты исходного запроса и выполняет Min() для [ID], Max() для [Comp] и [Rem] и GROUP BY для всего остального:

SELECT 
    Min(t.ID) AS MinOfID, 
    t.RecID, 
    Max(t.Comp) AS MaxOfComp, 
    Max(t.Rem) AS MaxOfRem, 
    t.Date_, 
    t.IDNEW, 
    t.IDOLD, 
    t.[CB?], 
    t.CallbackDate
FROM 
    (
        SELECT CBNEW.*
        FROM 
            CallbackNewID CBNEW 
            INNER JOIN 
            (
                SELECT IDNEW, MAX(CallbackDate) AS MaxDate 
                FROM CallbackNewID 
                GROUP BY IDNEW
            ) AS groupedCBNEW 
                ON (CBNEW.CallbackDate = groupedCBNEW.MaxDate) 
                AND (CBNEW.IDNEW = groupedCBNEW.IDNEW)
    ) t
GROUP BY 
    t.RecID, 
    t.Date_, 
    t.IDNEW, 
    t.IDOLD, 
    t.[CB?], 
    t.CallbackDate;

Это может быть не очень элегантно, но если это работает....

person Gord Thompson    schedule 04.11.2013
comment
Спасибо, я попытался, но в результате получилось на 3 записи больше, чем я ожидал, дубликаты найдены в столбце IDNEW. - person Jof Davies; 05.11.2013
comment
@user2953562 Достаточно ли полны примеры данных в SQL Fiddle здесь, чтобы проиллюстрировать проблема? - person Gord Thompson; 05.11.2013
comment
Это решает, что было не так с моим запросом. Я сначала не увидел. MIN и MAX в одной и той же группе возвращали недопустимые строки, которые были проигнорированы во внешнем JOIN. Это должно сделать это. Можете ли вы опубликовать 3 записи, о которых вы говорите в sqlfiddle? и все строки с одинаковой датой, идентификатором и идентификатором. - person Filipe Silva; 05.11.2013
comment
@user2953562 user2953562 Или вы можете создать новый SQL Fiddle с 4 записями: 3 дополнительных плюс тот, который вы в конечном итоге хотите сохранить. Это может помочь нам изолировать то, что вы действительно хотите ГРУППИРОВАТЬ ПО. - person Gord Thompson; 05.11.2013
comment
Я обновил скрипку и добавил 6 строк дубликатов (3 оставить). Я бы хотел первое появление любого обмана. Ну, во-первых, я имею в виду любое единичное происшествие. Спасибо еще раз. - person Jof Davies; 05.11.2013
comment
@ user2953562 Хорошо, если вы говорите о последних 6 строках, то они появляются, потому что COMP или REM разные. Итак, вы хотите ГРУППИРОВАТЬ ПО всему, кроме ID, COMP и REM? Если да, то должны ли значения COMP и REM поступать из той же строки, что и MinOfID, или они могут быть агрегатами Max() или Min()? - person Gord Thompson; 05.11.2013
comment
Ты хитрая лиса. Хороший глаз. Всегда берите максимальное значение для этих двух значений. - person Jof Davies; 05.11.2013

Я думаю, что в MS SQL Server вы ищете функцию ROW_NUMBER().

Что-то вроде этого должно помочь вам получить то, что вы ищете:

SELECT
    X.*
FROM
    (
        SELECT
            *,
            ROW_NUMBER() OVER (PARTITION BY DBNEW.IDNEW, DBNEW.MaxDate) [row_num]
        FROM
            CallbackNewID CBNEW 
            INNER JOIN 
            (
                SELECT
                    IDNEW,
                    MAX(CallbackDate) AS MaxDate
                FROM
                    CallbackNewID 
                GROUP BY
                    IDNEW
            ) AS groupedCBNEW ON (CBNEW.CallbackDate = groupedCBNEW.MaxDate) AND (CBNEW.IDNEW = groupedCBNEW.IDNEW)
    ) X
WHERE
    X.row_num = 1
person StyxUT    schedule 04.11.2013
comment
Доступ не поддерживает ROW_NUMBER(). - person Gord Thompson; 04.11.2013
comment
Боюсь, я довольно архаичен и строю в MS Access. - person Jof Davies; 04.11.2013

person    schedule
comment
Доступ не поддерживает ROW_NUMBER(). - person Gord Thompson; 04.11.2013