2011-01-13 3 views
0

У меня есть две идентичные таблицы: user_id, name, age, date_added. Столбец USER_ID может содержать несколько повторяющихся идентификаторов.SQL-запрос для объединения двух таблиц с дополнительными условиями?

Необходимо объединить эти 2 таблицы в 1 со следующим условием. Если для одного и того же пользователя есть несколько записей с одинаковым «именем», тогда необходимо сохранить только запись «ПОСЛЕДНИЕ» (по дате). Этот скрипт будет использоваться с MSSQL 2005, но будет также признателен, если кто-то придумает версию, которая не использует ROW_NUMBER(). Нужно, чтобы этот скрипт перезагружал сломанную таблицу один раз, производительность не критична.

пример:

table1:

1,'john',21,01/01/2010 

1,'john',15,01/01/2005 

1,'john',71,01/01/2001 

table2:

1,'john',81,01/01/2007 

1,'john',15,01/01/2005 

1,'john',11,01/01/2008 

результат:

1,'john',21,01/01/2010 

UPDATE: Я думаю, что я нашел свое собственное решение , Он основан на ответе на мой предыдущий вопрос, заданный Ларри Лустигом и Джо Стефанелли.

с tmp2 как ( SELECT * FROM table1 UNION
SELECT * FROM table2 )

SELECT * FROM tmp2 c1 ГДЕ (SELECT COUNT (*) FROM tmp2 c2 ГДЕ c2.user_id = c1.user_id И c2.name = c1.name И c2.date_added> = c1.date_added) < = 1

не могли бы вы мне помочь преобразовать этот запрос к одной без «WI TH '?

+1

Пожалуйста, разместите код, который вы написали. Люди обычно не любят просто писать свой код для вас. Как бы то ни было, это описание работы, а не вопрос. –

+0

Я все еще работаю над этим. Пока нет хорошего рабочего решения. Обязательно опубликуйте его здесь, если я придумаю один, прежде чем кто-то еще опубликует их здесь. – myforums

+0

начните с записи оператора select, который возвращает уникальные идентификаторы пользователя и максимальные даты - это простая группа, а затем заверните это в оператор insert. – Randy

ответ

0

Вы можете использовать not exists, как:

; with all_users as 
     (
     select * 
     from table1 u1 
     union all 
     select * 
     from table2 u2 
     ) 
select * 
from all_users u1 
where not exists 
     (
     select * 
     from all_users u2 
     where u1.name = u2.name 
       and u1.record_time < u2.record_time 
     ) 

Если база данных не поддерживает КТР разверните all_users в двух местах она используется.

P.S. Если не только три колонны, и не более того, вы можете использовать еще более простое решение:

select name 
,  MAX(record_time) 
from (
     select * 
     from table1 u1 
     union all 
     select * 
     from table2 u2 
     ) sub 
group by 
     name 
+0

Что-то не так с 1-м решением. Я думаю, что «где» должно быть, чтобы u1.user_id = u2.user_id и что-то еще. Второе решение не очень хорошо, потому что оно не выбирает AGE. В моей реальной таблице больше столбцов, чем указано в описании. – myforums

+0

@myforums: Вы правы, ответ отредактирован – Andomar

0

Вот вариант @ ответ Andomar в:

; with all_users as 
    (
    select * 
    from table1 u1 
    union all 
    select * 
    from table2 u2 
    ) 
, ranker as (
    select *, 
    rank() over (partition by userid order by recordtime) as [r] 
) 
select * from ranker where [r] = 1 
0

Просто в интересах предоставления другого подхода ...

WITH distinctlist 
    As (SELECT user_id, 
       name 
     FROM table1 
     UNION 
     SELECT user_id, 
       name 
     FROM table2) 
SELECT C.* 
FROM distinctlist d 
     CROSS APPLY (SELECT TOP 1 * 
        FROM (SELECT TOP 1 * 
          FROM table1 
          WHERE user_id = d.user_id 
            AND name = d.name 
          ORDER BY date_added DESC 
          UNION ALL 
          SELECT TOP 1 * 
          FROM table1 
          WHERE user_id = d.user_id 
            AND name = d.name 
          ORDER BY date_added DESC) T 
        ORDER BY date_added DESC) C 
Смежные вопросы