Последняя запись таблицы соединений (как оптимизировать) - PullRequest
0 голосов
/ 09 сентября 2009

У меня та же «проблема», как описано в ( Последняя запись таблицы соединений ): мне нужно присоединиться к «основной таблице» с «таблицей истории», тогда как я хочу присоединиться только к самой последней (по дате) Запись таблицы истории. Поэтому, когда я запрашиваю запись для мастер-таблицы, я также получаю «последние» данные из таблицы истории.

Master Table
  ID
  FIRSTNAME
  LASTNAME
  ...

History Table
  ID
  LASTACTION
  DATE

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

Мои вопросы: Как я могу решить проблему, что в теории могут быть две записи истории с одной и той же датой?

Является ли такое объединение с подвыбором действительно лучшим решением с точки зрения производительности (и вообще)? Что вы думаете (я не эксперт по всем этим вещам), если я добавлю еще один атрибут в таблицу истории, который называется «ISLATESTRECORD», как логический флаг, которым я управляю вручную (и который имеет уникальные ограничения). Этот атрибут затем будет явно отмечать последнюю запись, и мне не нужны никакие подвыборы, поскольку я могу напрямую использовать этот атрибут в предложении where в соединении. С другой стороны, это делает вставку новой записи, конечно, немного более сложной: сначала я должен удалить флаг «ISLATESTRECORD» из последней записи, мне нужно вставить новую запись истории с набором «ISLATESTRECORD» и зафиксировать перевод.

Как вы думаете, что является рекомендуемым решением? Я не имею ни малейшего представления о влиянии вложенных элементов на производительность: у меня могут быть миллионы «Mastertable» записей », которые мне нужно искать для конкретной записи, также использующей в атрибутах поиска объединенной таблицы History, например:« Дайте мне Mastertable Record с именем FIRSTNAME XYZ и LASTACTION (из таблицы истории) было «измененное имя». Так что этот отбор может быть назван миллионы раз.

Или лучше работать с подвыбором, чтобы найти последнюю запись, поскольку подвыборы очень эффективны и лучше поддерживать все в норме?

Большое спасибо

Ответы [ 2 ]

2 голосов
/ 09 сентября 2009

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

Чтобы решить проблему с вашими таблицами (с примером кода SQL Server):

DECLARE @MasterTable table (MasterID int,FirstName varchar(20),LastName varchar(20))
DECLARE @HistoryTable table (MasterID int,LastAction char(1),HistoryDate datetime)

INSERT INTO @MasterTable VALUES (1,'AAA','aaa')
INSERT INTO @MasterTable VALUES (2,'BBB','bbb')
INSERT INTO @MasterTable VALUES (3,'CCC','ccc')

INSERT INTO @HistoryTable VALUES (1,'I','1/1/2009')
INSERT INTO @HistoryTable VALUES (1,'U','2/2/2009')
INSERT INTO @HistoryTable VALUES (1,'U','3/3/2009')  --<<dups
INSERT INTO @HistoryTable VALUES (1,'U','3/3/2009')  --<<dups
INSERT INTO @HistoryTable VALUES (2,'I','5/5/2009')
INSERT INTO @HistoryTable VALUES (3,'I','7/7/2009')
INSERT INTO @HistoryTable VALUES (3,'U','8/8/2009')

SELECT
    MasterID,FirstName,LastName,LastAction,HistoryDate
    FROM (SELECT
              m.MasterID,m.FirstName,m.LastName,h.LastAction,h.HistoryDate,ROW_NUMBER() OVER(PARTITION BY m.MasterID ORDER BY m.MasterID) AS RankValue
              FROM @MasterTable m
                  INNER JOIN (SELECT
                                  MasterID,MAX(HistoryDate) AS MaxDate
                                  FROM @HistoryTable
                                  GROUP BY MasterID
                             ) dt ON m.MasterID=dt.MasterID
                  INNER JOIN @HistoryTable h ON dt.MasterID=h.MasterID AND dt.MaxDate=h.HistoryDate
         ) AllRows
    WHERE RankValue=1

ВЫВОД:

MasterID    FirstName LastName LastAction HistoryDate
----------- --------- -------- ---------- -----------
1           AAA       aaa      U          2009-03-03 
2           BBB       bbb      I          2009-05-05 
3           CCC       ccc      U          2009-08-08 

(3 row(s) affected)

Чтобы решить проблему с улучшенной историей (с примером кода SQL Server): это лучше, потому что он имеет автоматически увеличивающийся столбец идентификатора идентификатора истории

DECLARE @MasterTable table (MasterID int,FirstName varchar(20),LastName varchar(20))
DECLARE @HistoryTableNEW table (HistoryID int identity(1,1), MasterID int,LastAction char(1),HistoryDate datetime)

INSERT INTO @MasterTable VALUES (1,'AAA','aaa')
INSERT INTO @MasterTable VALUES (2,'BBB','bbb')
INSERT INTO @MasterTable VALUES (3,'CCC','ccc')

INSERT INTO @HistoryTableNEW VALUES (1,'I','1/1/2009')
INSERT INTO @HistoryTableNEW VALUES (1,'U','2/2/2009')
INSERT INTO @HistoryTableNEW VALUES (1,'U','3/3/2009')  --<<dups
INSERT INTO @HistoryTableNEW VALUES (1,'U','3/3/2009')  --<<dups
INSERT INTO @HistoryTableNEW VALUES (2,'I','5/5/2009')
INSERT INTO @HistoryTableNEW VALUES (3,'I','7/7/2009')
INSERT INTO @HistoryTableNEW VALUES (3,'U','8/8/2009')

SELECT
    m.MasterID,m.FirstName,m.LastName,h.LastAction,h.HistoryDate,h.HistoryID
    FROM @MasterTable m
        INNER JOIN (SELECT
                        MasterID,MAX(HistoryID) AS MaxHistoryID
                        FROM @HistoryTableNEW
                        GROUP BY MasterID
                   ) dt ON m.MasterID=dt.MasterID
        INNER JOIN @HistoryTableNEW h ON dt.MasterID=h.MasterID AND dt.MaxHistoryID=h.HistoryID

ВЫВОД:

MasterID    FirstName LastName LastAction HistoryDate             HistoryID
----------- --------- -------- ---------- ----------------------- ---------
1           AAA       aaa      U          2009-03-03 00:00:00.000 4
2           BBB       bbb      I          2009-05-05 00:00:00.000 5
3           CCC       ccc      U          2009-08-08 00:00:00.000 7

(3 row(s) affected)
0 голосов
/ 09 сентября 2009

Если у таблицы истории есть первичный ключ (и все таблицы должны), вы можете изменить подвыбор, чтобы извлечь запись с большим (или меньшим) значением PK кратных, соответствующих критерию даты ...

  Select M.*, H.* 
  From Master M
     Join History H 
         On H.PK = (Select Max(PK) From History
                    Where FK = M.PK
                       And Date = (Select Max(Date) From History
                                   Where FK = M.PK))

Что касается производительности, то это можно решить, добавив соответствующие индексы в эти таблицы (History.Date, History.FK), но в целом, в зависимости от конкретных шаблонов распределения данных таблиц, подзапросы могут отрицательно влиять на производительность.

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