2016-06-14 3 views
2

Как я могу выполнить внутреннее соединение и выбрать только одну строку из строк с одинаковыми столбцами?Как получить определенные строки во внутреннем соединении SQL

, например:

enter image description here enter image description here

если выполнить запрос:

SELECT t1.col1, t2.col3 
FROM t1 INNER JOIN t2 
ON t1.col2=t2.col2; 

Я получаю таблицу

enter image description here

Но я хочу, чтобы получить только один ряд (верхний) для каждого значения в col1

enter image description here

Есть идеи?

Спасибо!

+0

ГРУППА BY/MIN() –

+2

«(верхняя)» - как вы * определяете * верх в этом обстоятельстве? Таблицы не имеют неотъемлемого порядка. Итак, это строка с наименьшим значением '' col3'? Или какое-либо другое правило, использующее некоторые другие (не показаны) столбцы (столбцы)? –

+0

@ AllanS.Hansen, и что, если значения в col3 были «a, b, c» вместо «10,20,30»? MIN работает? –

ответ

0

Вы можете использовать запрос, как следующее:

SELECT t1.col1, t2.col3 
FROM t1 
INNER JOIN (
    SELECT col2, MIN(col3) AS col3 
    FROM t2 
    GROUP BY col2 
) AS t2 ON t1.col2=t2.col2; 
+1

Нет. Это даст минимальное не первое значение для col3 –

+2

@ChaosLegion Нет такой вещи, как * первое значение *. Таблицы SQL являются * неупорядоченными наборами *, а приоритет определяется конкретным столбцом. Из контекста, представленного в OP, я предполагаю, что поле в этом случае является 'col3'. –

+0

Да. Его требование является ТОП первым. Трудно ли изменить ваш ответ? –

3

Вы можете попробовать функцию окна

SELECT T.col1, T.col3 
FROM (
    SELECT t1.col1, t2.col3 , 
      ROW_NUMBER() over (partition by t1.col1 order by t2.col3) as orden 
    FROM t1 INNER JOIN t2 
     ON t1.col2=t2.col2) as T 
WHERE T.orden = 1; 
+0

Спасибо, отличная идея! –

2

Один больше путь с наружными ОБРАЩАТЬСЯ:

SELECT t1.col1,p.col3 
FROM t1 
OUTER APPLY (
    SELECT TOP 1 * 
    FROM t2 
    WHERE t1.col2 = t2.col2) as p 

Выход :

col1 col3 
1  10 
2  30 
+0

Спасибо! Я не знал «внешнее применение». –

+1

Отлично, если вы нашли что-то новое! Дополнительные технические подробности и примеры можно получить здесь https://www.mssqltips.com/sqlservertip/1958/sql-server-cross-apply-and-outer-apply/ – gofr1

1
You can also use below 

Select Col1,Col3 From (
    SELECT Col1,Col3,DENSE_RANK() OVER (PARTITION BY t2.Col2 ORDER BY Col3) rank 
     FROM T2 JOIN T1 on T2.col2=T1.col2) Tr where rank=1 
+0

Спасибо! это похоже на решение, предлагаемое @vercelli .. –

+0

@OrK: это не то же самое, поскольку у вас может быть несколько строк с рамом = 1 – vercelli

+0

Согласитесь с @vercelli, но это будет работать с вашей проблемой. –

1

Все ответы правильные .. но некоторые из них приведут к другому или даже худшему, непредсказуемому результату (не детерминированным).

в решении 1) группа за/мин от @ AllanS.Hansen и @GiorgosBetsos вы получите только одну строку t2 для каждой строки в t1. Строка будет выбрана с помощью функции min(), которая определена для почти каждого типа данных.

раствор 2) row_number = 1 от @vercelli такой же раствора 1) держать первый заказ значение с помощью COL3 ASC это то же самое из MIN()

обратите внимание! решение 3) внешнее применение от @ gofr1 похоже, но оно не гарантирует выход, верхняя функция может давать разные результаты при каждом прогоне, если вы не укажете заказом col3 (оптимизатор будет решать в зависимости от по индексам или кластеризованным ключам). Если вы укажете его, он даст тот же результат решения 1) и solution 2)

вы должны решить, что ТОП означает для вас, он может отличаться от значения функции TOP сервера sql.

Я думаю, что лучшим решением является добавление столбца в порядке сортировки.

Вы можете использовать целочисленный столбец, например 1,2,3 для порядка сортировки, или использовать идентификатор. В этом случае вы также будете иметь «вставки заказ»

Я избежать OUTER APPLY, поскольку он выполняется для каждой строки t1 и медленнее, чем другие решения.

+0

Спасибо, я узнал от вас комментарий много! –