Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 OUTER APPLY - неправильный результат работы TOP 1  [new]
SiNtez_26
Member

Откуда:
Сообщений: 199
Всем привет.
Вообщем, столкнулся со странной проблемой, помощь в решений которой хотелось бы попросить.
Есть две таблицы - TABLE1 и TABLE2. Первая содержит записи, которые могут несколько раз дублироваться. Вторая содержит выборку из первой, но записи являются уникальными. Иногда, во второй таблице может быть две почти полностью совпадающие записи, за исключение одного поля. Нам это не нужно. Чтобы это обойти, мы формируем уникальные строчки с помощью OUTER APPLY. Сначала создаем временную таблицу, в нее записываем нам нужные, только уникальные идентификаторы, по которым будут отбираться строки (допустим, ID1):
INSERT INTO #TEMP (ID1)
SELECT DISTINCT(ID1)
FROM dbo.TABLE2

Потом прикрепляем к ним значения с помощью OUTER APPLY:
SELECT tt.ID1, name.NAME
FROM #TEMP AS tt
    OUTER APPLY (SELECT TOP 1 NAME FROM dbo.TABLE2
                        WHERE NAME IS NOT NULL AND ID1 IS NOT NULL AND ID1 = tt.ID1) AS name

Но в итоге получаем для все уникальных ID1 одно и то же NAME - самое первое в таблице.
В то же время, если заменить внутри OUTER APPLY TABLE2 на TABLE1 (где много неуникальных значений), то все сработает как надо.
Вопрос такой: я неправильно понимаю логику работы APPLY, или косяк в чем-то другом?
8 ноя 13, 14:03    [15097497]     Ответить | Цитировать Сообщить модератору
 Re: OUTER APPLY - неправильный результат работы TOP 1  [new]
Glory
Member

Откуда:
Сообщений: 104751
WHERE NAME IS NOT NULL AND ID1 IS NOT NULL AND ID1 - вы наверное считаете, что раз это подзапрос, то поле ID1 без алиаса должно непременно быть из "внутренней" таблицы ?
8 ноя 13, 14:10    [15097554]     Ответить | Цитировать Сообщить модератору
 Re: OUTER APPLY - неправильный результат работы TOP 1  [new]
SiNtez_26
Member

Откуда:
Сообщений: 199
Вы знаете, так до этого момента и было. Спасибо вам.
8 ноя 13, 14:21    [15097624]     Ответить | Цитировать Сообщить модератору
 Re: OUTER APPLY - неправильный результат работы TOP 1  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6201
Здесь в общем-то и никаких временных таблиц не надо:
;with cte as (
  select ID1, name, row_number() over(partition by ID1 order by name) ord
  from dbo.Table2
)
select id1, name from cte where ord=1 
8 ноя 13, 14:27    [15097660]     Ответить | Цитировать Сообщить модератору
 Re: OUTER APPLY - неправильный результат работы TOP 1  [new]
SiNtez_26
Member

Откуда:
Сообщений: 199
Насколько я знаю, WITH может быть одним, а мы, к сожалению, его уже используем для этого запроса.
8 ноя 13, 14:32    [15097705]     Ответить | Цитировать Сообщить модератору
 Re: OUTER APPLY - неправильный результат работы TOP 1  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6201
SiNtez_26
Насколько я знаю, WITH может быть одним, а мы, к сожалению, его уже используем для этого запроса.

WITH - один, а CTE - сколько угодно:
;with cte as (
  select ID1, name, row_number() over(partition by ID1 order by id1) ord
  from dbo.Table2
), cte2 as (
  select number n1, number*100 n2 from master..spt_values where type='P' and number between 0 and 5
), cte3 as (
  select e1.id1, e1.name, e2.n2
  from cte e1
  join cte2 e2 on e1.id1=e2.n1
  where e1.ord=1
)
select * from cte3
8 ноя 13, 14:40    [15097795]     Ответить | Цитировать Сообщить модератору
 Re: OUTER APPLY - неправильный результат работы TOP 1  [new]
SiNtez_26
Member

Откуда:
Сообщений: 199
Спасибо вам, не знал о такой возможности.
8 ноя 13, 14:42    [15097812]     Ответить | Цитировать Сообщить модератору
 Re: OUTER APPLY - неправильный результат работы TOP 1  [new]
SiNtez_26
Member

Откуда:
Сообщений: 199
Сон Веры Павловны,

А вы не могли бы просветить меня насчет производительности cte и темповых таблиц?
8 ноя 13, 15:08    [15098020]     Ответить | Цитировать Сообщить модератору
 Re: OUTER APPLY - неправильный результат работы TOP 1  [new]
Сон Веры Павловны
Member

Откуда:
Сообщений: 6201
SiNtez_26,

Здесь в первую очередь роль играет не производительность, а возможности использования - вы не сможете использовать временные таблицы в table-valued function/view. Альтернативой может быть использование табличных переменных в multistatement table-valued function, но у табличных переменных а) определение индексов возможно только через constraints (primary key/unique); 2) даже при наличии индексов на табличной переменной существуют проблемы их (индексов) использования (см., например, здесь). CTE же вполне можно использовать в инлайновых функциях, и при должной оптимизации это будет налучшим вариантом.
8 ноя 13, 15:24    [15098126]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить