присоединение последних различных тегов метаданных пользователя к строкам пользователя

StackOverflow https://stackoverflow.com/questions/25224

  •  09-06-2019
  •  | 
  •  

Вопрос

У меня есть база данных postgres с таблицей пользователей (идентификатор пользователя, имя, фамилия) и таблицей метаданных пользователя (идентификатор пользователя, код, контент, дата и время создания).Я храню различную информацию о каждом пользователе в таблице usermetadata по коду и веду полную историю.например, пользователь (идентификатор пользователя 15) имеет следующие метаданные:

15, 'QHS', '20', '2008-08-24 13:36:33.465567-04'  
15, 'QHE', '8', '2008-08-24 12:07:08.660519-04'  
15, 'QHS', '21', '2008-08-24 09:44:44.39354-04'  
15, 'QHE', '10', '2008-08-24 08:47:57.672058-04'  

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

Это было полезно?

Решение

Полагаю, вы не хотите изменять свою схему, поэтому боюсь, что мой ответ может оказаться бесполезным, но вот...

Одним из возможных решений было бы оставить поле времени пустым до тех пор, пока оно не будет заменено более новым значением, когда вместо этого вы вставите «дату прекращения поддержки».Другой способ — расширить таблицу «активным» столбцом, но это приведет к некоторой избыточности.

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

Общим для них является то, что существует единственный способ определения набора текущих полей.Вы просто выбираете все записи с активным пользователем и NULL «Действителен», или «Дата прекращения поддержки», или настоящий «активный».

Возможно, вам будет интересно взглянуть на статью в Википедии: временные базы данных и статья Согласованный глоссарий концепций временных баз данных.

Другие советы

На самом деле это не так уж сложно сделать в PostgreSQL, поскольку он имеет "ОТЛИЧНЫЙ НА" в синтаксисе SELECT (DISTINCT ON не является стандартным SQL).

SELECT DISTINCT ON (code) code, content, createtime
FROM metatable
WHERE userid = 15
ORDER BY code, createtime DESC;

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

Подзапрос — это стандартный способ сделать это.Вам просто нужно уникальное ограничение для UserId, Code и Date, а затем вы можете запустить следующее:

SELECT * 
FROM Table
JOIN (
   SELECT UserId, Code, MAX(Date) as LastDate
   FROM Table
   GROUP BY UserId, Code
) as Latest ON
   Table.UserId = Latest.UserId
   AND Table.Code = Latest.Code
   AND Table.Date = Latest.Date
WHERE
   UserId = @userId
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top