Вопрос-запрос по реляционной базе данных - PullRequest
2 голосов
/ 19 мая 2011

У меня есть вопрос о конкретном запросе, который я хотел бы выполнить к таблице PostgreSQL. Хотя я приветствую критику схемы таблиц, которую я использовал, я буду более благодарен за ответы на мой актуальный вопрос!

Я использую модуль uuid-ossp postgresql-contrib и имею следующую структуру таблицы:

       Column        |            Type             | Modifiers | Storage  | Description
---------------------+-----------------------------+-----------+----------+-------------
 revision_id         | uuid                        | not null  | plain    |
 document_id         | uuid                        | not null  | plain    |
 user_id             | uuid                        | not null  | plain    |
 datetime_edited     | timestamp without time zone | not null  | plain    |
 contents            | text                        | not null  | extended |
Indexes:
    "document_pkey" PRIMARY KEY, btree (revision_id)

Идея такова:

  • Документ может иметь одну или несколько ревизий. Редакции не удаляются. Для обновления документа вставляется новая строка с новым revision_id, но идентичным document_id.
  • revision_id уникален во всех редакциях для всех документов.
  • contents - это блок данных, представляющий документ, а user_id определяет, кто обновил документ.

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

select * from document where user_id = '6a2aabc417b34ef99b14b10eaa8e9313';

но это возвращает все документы. Как выполнить детализацию и запросить группировку по document_id, а также LIMIT 1 и вернуть новейшие revision_id на основе datetime_edited?

РЕДАКТИРОВАТЬ: Так как документ может иметь одну или несколько ревизий, я был весьма смутным, говоря: «все документы созданы пользователем». Под созданным я подразумеваю, что пользователь внес одну или несколько ревизий в документы, то есть существует хотя бы одна ревизия, в которой пользователь отредактировал документ.

Возможно ли что-то подобное в одном запросе или мне нужно несколько раз обратиться к базе данных, чтобы достичь этого?

РЕДАКТИРОВАТЬ: revision_id не монотонно увеличивается. Это случайный UUID. Следовательно, max (revision_id)! = Max (datetime_edited).

Ответы [ 2 ]

2 голосов
/ 19 мая 2011
Select ...
From document As D
    Join    (
            Select D1.document_id, Max( datetime_edited ) As datetime_edited
            From document As D1
            Group By D1.document_id
            ) As LastRevision
        On LastRevision.document_id = D.document_id
            And LastRevision.datetime_edited = D.datetime_edited
Where Exists    (
                Select 1
                From document As D2
                Where D2.document_id = D.document_id
                    And D2.user_id = '6a2aabc417b34ef99b14b10eaa8e9313'
                )

Альтернативная форма:

Select ...
From document As D
    Join    (
            Select D1.document_id, Max( datetime_edited ) As datetime_edited
            From document As D1
            Group By D1.document_id
            ) As LastRevision
        On LastRevision.document_id = D.document_id
            And LastRevision.datetime_edited = D.datetime_edited
    Join    (
            Select D2.document_id
            From document As D2
            Where D2.user_id = '6a2aabc417b34ef99b14b10eaa8e9313'
            Group By D2.document_id
            ) As UserDocs
        On UserDocs.document_id = D.document_id
2 голосов
/ 19 мая 2011

Получите максимальный идентификатор редакции для каждого документа, затем выберите эти документы:

select *
from document
where revision_id in (
  select max(revision_id)
  from document
  where user_id = '6a2aabc417b34ef99b14b10eaa8e9313'
  group by document_id
)

Обновление:

Поскольку идентификатор версии не является инкрементным, вам придется выбрать идентификатор_документа и его последнюю дату / время редактирования, а также объединиться с таблицей документов:

select d.*
from document d
inner join (
  select document_id, max(datetime_edited) as datetime_edited
  from document
  where user_id = '6a2aabc417b34ef99b14b10eaa8e9313'
  group by document_id
) x on x.document_id = d.document_id and x.datetime_edited = d.datetime_edited
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...