2009-10-09 2 views
1

Я должен уметь ссылаться на таблицы в предложениях соединения из подзапроса, не так ли?Присоединиться к подзапросу не работает?

Но следующий запрос дает мне ошибки, говоря, что они не могут быть связаны:

select * 
from call c 
JOIN call_task ct ON c.call_no=ct.call_no AND ct.calltask_no = (select min(ict.calltask_no) FROM call_task ict WHERE ict.call_no=c.call_no) 
JOIN business b ON c.service_business_id=b.business_id 
JOIN item i ON ct.item_id=i.item_id 
JOIN ( select top 1 * 
      FROM contract_line icl 
      WHERE icl.item_id = i.item_id 
       AND icl.location_no = c.service_location_no 
       AND icl.business_id = b.business_id 
      ORDER BY icl.cancel_date asc 
     ) cl ON i.item_id=cl.item_id 
      AND cl.location_no=c.service_location_no 
      AND cl.business_id=b.business_id 
JOIN [contract] co ON cl.cont_no=co.cont_no 
JOIN business_location bl ON bl.business_id=c.service_business_id AND bl.location_no=c.service_location_no 
WHERE b.bus_code='INGRAM04' 
AND ct.cont_no is null 
AND call_sts NOT IN ('BB', 'BI', 'CA', 'CL', 'IP') 
--AND cl.end_date > c.entry_date 
ORDER BY c.create_time 

Ошибки: Msg 4104, уровень 16, состояние 1, строка 1 Мульти-часть идентификатора " i.item_id "не может быть привязан. Msg 4104, уровень 16, состояние 1, строка 1 Идентификатор из нескольких частей "c.service_location_no" не может быть связан. Msg 4104, уровень 16, состояние 1, строка 1 Идентификатор из нескольких частей "b.business_id" не может быть связан.

Я не понимаю, почему я получаю эти ошибки и не могу думать ни о чем. Item_no в contract_line может появляться более одного раза в контракте, если он был отменен и, например, создана новая строка. В этих случаях мне нужно игнорировать отмененную линию и вытащить текущую. Выполнение подзапроса и упорядочивание с помощью cancel_date сначала выталкивает нули, чтобы он выполнял то, что я хочу ... но эта странная ошибка привязки меня заворачивает. Я знаю, что я использовал эту технику раньше, так что теперь я запутался ...

ответ

5

Вы не можете использовать зависимые подзапросы в JOIN. Вместо этого используйте APPLY. Использование примера KM:

declare @table table (t int); 
select  t1.t  
from @table t1  
cross apply (select t2.t from @table t2 where t1.t=t2.t) as dt 
+1

Взял меня некоторое время, чтобы понять CROSS ОТНОСИТЬСЯ ... но что сделал трюк. (Я по-прежнему клянусь, что раньше делал подзапрос, хотя ...) – CodeRedick

+0

Существуют некоторые семантические различия между JOIN и APPLY, поэтому вам нужно проявлять осторожность, но в целом, когда вы хотите присоединиться к набору правой стороны, который зависит в текущей строке набора слева, APPLY - это путь. Учитывая, что у вас есть TOP и ORDER, которые должны применять * после * ГДЕ, зависящие от псевдонимов c и b, я считаю APPLY подходящим. –

1

Ошибка Я считаю, что исходит от выбора вы альясинга с сл затем пытается присоединиться на

WHERE icl.item_id = i.item_id 
AND icl.location_no = c.service_location_no 
AND icl.business_id = b.business_id 

вы можете Здесь указаны «i» и «c» и «b».

0

, который не является подзапросом, а производная таблица (или некоторые называют ее встроенным видом). вот простой запрос, чтобы показать ту же проблему:

declare @table table (t int) 
select 
    t1.t 
    from @table t1 
    inner join (select t2.t from @table t2 where t1.t=t2.t) dt on 1=1 

Msg 4104, Level 16, State 1, Line 2 
The multi-part identifier "t1.t" could not be bound. 

все между () изолирован от внешнего запроса.

это подзапрос, который работает:

select 
    t1.t 
    from @table t1 
    WHERE exists (select * from @Table t2 where t1.t=t2.t) 

ВЫВОД:

t 
----------- 

(0 row(s) affected) 
Смежные вопросы