Уникальность на основе наибольшего значения, когда не все ячейки одинаковы - PullRequest
1 голос
/ 21 мая 2009

Допустим, у меня есть следующая таблица результатов из моего выбора SQL:

DocumentId        CreationDate       InstanceId
ABC               10th Jan           0c60f4e2-02fc-4244-9ec5-4d259ea5774d
ABC               11th Jan           2168ab5d-d6ca-4db3-90f0-b621d72108b8
BCA               4th Jan            cb7cdf24-b50f-4bd9-b2b5-d58a14793dd8

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

Как бы я изменил свой выбор, чтобы я возвращал только одну строку на DocumentId, выбирая «новейший» (определяется CreationDate), убедившись, что InstanceId в строке - правильный. 1010 *

Таким образом, приведенный выше пример вместо этого вернет:

DocumentId        CreationDate       InstanceId
ABC               11th Jan           2168ab5d-d6ca-4db3-90f0-b621d72108b8
BCA               4th Jan            cb7cdf24-b50f-4bd9-b2b5-d58a14793dd8

(кстати, извините за ужасный заголовок вопроса, не стесняйтесь сменить его на что-то более подходящее)

Ответы [ 3 ]

1 голос
/ 21 мая 2009

Вот версия для SQL Server. По сути, вы объединяете таблицу с таблицей, полученной путем группировки строк по столбцу DocumentId и получения max (creationDate). Используя эти 2 столбца как условие для получения значения кода. В основном первичный ключ для требуемого выбора - DocumentName и CreationDate. Они однозначно (или должны уникально) идентифицировать строку, которую вы пытаетесь выбрать. Чтобы получить этот ключ, мы создаем вторую (временную) таблицу с предложением select и groupBy. Мы соединяем эту таблицу с оригинальной и используем информацию для выбора.

SELECT
     mt2.DocumentId
    ,mt2.CreationDate
    ,mt1.InstanceId
FROM
    myTable    mt1
    inner join (SELECT 
                     DocumentId  DocumentId
                    ,MAX(CreationDate)  CreationDate
             FROM       
                     myTable
             GROUP BY 
                     DocumentId
               )mt2  on  mt2.DocumentId = mt1.DocumentId 
                     and mt2.CreationDate = mt1.CreationDate
ORDER BY mt2.DocumentId

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

1 голос
/ 21 мая 2009

Пример для Oracle:

SELECT DISTINCT
       DocumentId,
       FIRST_VALUE(CreationDate)
          OVER (PARTITION BY DocumentId
                ORDER BY CreationDate DESC) AS CreationDate,
       FIRST_VALUE(InstanceId)
          OVER (PARTITION BY DocumentId
                ORDER BY CreationDate DESC) AS InstanceId
FROM   mytable;

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

0 голосов
/ 21 мая 2009

Это должно работать на большинстве баз данных:

SELECT
    cur.DocumentId, cur.CreationDate, cur.InstanceId
FROM
    DocumentVersions cur
LEFT OUTER JOIN
    DocumentVersions next
    ON next.DocumentId = cur.DocumentId
    AND next.CreationDate > cur.CreationDate 
WHERE
    next.DocumentId is null

Он объединяет таблицу Document против себя, ища документ с тем же идентификатором и более высокой CreationDate. Оператор where говорит, что документ с более высокой датой не должен быть найден, эффективно фильтруя самый новый документ по DocumentId.

Если может быть несколько документов с одной и той же датой создания, вы можете выбрать один с самым высоким InstanceId, например:

SELECT
    cur.DocumentId, cur.CreationDate, max(cur.InstanceId)
FROM
    DocumentVersions cur
LEFT OUTER JOIN
    DocumentVersions next
    ON next.DocumentId = cur.DocumentId
    AND next.CreationDate > cur.CreationDate 
WHERE
    next.DocumentId is null
GROUP BY
    cur.DocumentId, cur.CreationDate
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...