2009-06-22 5 views
4

Это должно быть достаточно простым, но почему-то мой мозг перестает работать.Ограниченный T-SQL Присоединиться

У меня есть два связанных таблиц:

Таблица 1:

ID (PK), Value1 

Таблица 2:

BatchID, Table1ID (FK to Table 1 ID), Value2 

Пример данные:

Таблица 1:

ID Value1 
1 A 
2 B 

Таблица 2:

BatchID Table1ID Value2 
1  1   100 
2  1   101 
3  1   102 
1  2   200 
2  2   201 

Теперь для каждой записи в таблице 1, я хотел бы сделать соответствующую запись в таблице 2, но только самый последний (партия ID последователен). Результатом для вышеуказанного примера будет:

Table1.ID Table1.Value1 Table2.Value2 
1   A    102 
2   B    201 

Проблема проста, как ограничить результат соединения таблицей 2. Были похожие вопросы о SO, но они не могут найти ничего похожего на мое. Вот один из MySQL, который выглядит аналогичным: LIMITing an SQL JOIN

Я открыт для любого подхода, хотя скорость по-прежнему остается основным приоритетом, так как это будет большой набор данных.

+0

Какую версию SQL Server? – AakashM

ответ

10
WITH Latest AS (
    SELECT Table1ID 
     ,MAX(BatchID) AS BatchID 
    FROM Table2 
    GROUP BY Table1ID 
) 
SELECT * 
FROM Table1 
INNER JOIN Latest 
    ON Latest.Table1ID = Table1.ID 
INNER JOIN Table2 
    ON Table2.BatchID = Latest.BatchID 
+0

Не будет ли тег SQL-Server указывать MS SQL и аннулировать его с помощью предложения Oracle 'With'? – madcolor

+3

Общие выражения таблиц (CTE) были введены в SQL Server 2005, этот ответ верен. – TheTXI

-1

Либо GROUP BY или ИНЕКЕ, что фильтры на самые последние:

SELECT * FROM Table1 a 
INNER JOIN Table2 b ON (a.id = b.Table1ID) 
WHERE NOT EXISTS(
     SELECT 1 FROM Table2 c WHERE c.Table1ID = a.id AND c.BatchID > b. BatchID 
) 
+0

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

+0

-1 потому что это была всего лишь общая попытка пройти ответ. Кроме того, вы можете видеть, что чистая GROUP BY/WHERE не будет работать здесь. Вам нужен CTE, как то, что сделал Кейд, или подзапрос. – Eric

+0

Я добавлял пример. Согласитесь, что я должен был быть яснее, указав подзапрос как «предложение WHERE, которое фильтрует самые последние». –

3
SELECT id, value1, value2 
FROM (
     SELECT t1.id, t2.value1, t2.value2, ROW_NUMBER() OVER (PARTITION BY t1.id ORDER BY t2.BatchID DESC) AS rn 
     FROM table1 t1 
     JOIN table2 t2 
     ON  t2.table1id = t1.id 
     ) q 
WHERE rn = 1 
+0

Хм ... как производительность подзапроса по сравнению с CTE? –

+0

@Adrian: это то же самое – Quassnoi

+3

Вы должны просто запустить оба оператора в том же окне с помощью «Включить план выполнения». Затем вы получите% стоимости для каждого заявления. –

0

Попробуйте

select t1.*,t2.Value2 
from(
select Table1ID,max(Value2) as Value2 
from [Table 2] 
group by Table1ID) t2 
join [Table 1] t1 on t2.Table1ID = t1.id 
Смежные вопросы