2009-09-09 5 views
0

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

Master Table 
    ID 
    FIRSTNAME 
    LASTNAME 
    ... 

History Table 
    ID 
    LASTACTION 
    DATE 

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

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

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

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

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

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

+0

Какую базу данных (вкл. версия)? –

ответ

2

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

Чтобы решить проблему с таблиц (с примером 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) 

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

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

Если таблица истории имеет первичный ключ (и все таблицы должны), вы можете изменить подзапрос, чтобы извлечь запись с либо больше (или меньше) 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), но в целом, в зависимости от конкретных данных таблицы распределения, подзапросы могут отрицательно влиять на производительность.

Смежные вопросы