Jak zrobić złączenie więcej niż jednej tabeli z FROM

0

Witajcie,

Stosunkowo od niedawna zajmuję się MSSQL (wcześniej PostgreSQL i Oracle) i natknąłem na dziwny problem. Otóż mam zapytanie:

select case when s1.IDDictStatuses is null then cast([TO].IDDictStatus as varchar) else s1.StatusName end as "StatusOperatora", 
       [e].IDDictStatus "StatusZadania"      
  from dbo.Task t, dbo.TaskExt e, dbo.TaskOperators [TO]
  left outer join dbo.DictStatuses s1 on ([TO].IDDictStatus = s1.IDDictStatuses)
 where t.IDTask = 10101
   and t.IDTask = e.IDTask
   and t.IDTask = [TO].IDTask

Zasadniczo zapytanie zwraca mi dwie kolumny z nazwą zadania operatora i numerem statusu samego zadania. Niby wszystko pięknie ale chciałbym jednak pokazać nazwę zamiast numeru statusu zadania no więc przerabiamy zapytanie na poniższe:

select case when s1.IDDictStatuses is null then cast([TO].IDDictStatus as varchar) else s1.StatusName end as "StatusOperatora", 
       case when s2.IDDictStatuses is null then cast(e.IDDictStatus as varchar) else s2.StatusName end as "StatusZadania"         
  from dbo.Task t, dbo.TaskExt e, dbo.TaskOperators [TO]
  left outer join dbo.DictStatuses s1 on ([TO].IDDictStatus = s1.IDDictStatuses)
  left outer join dbo.DictStatuses s2 on (e.IDDictStatus = s2.IDDictStatuses)
 where t.IDTask = 10101
   and t.IDTask = e.IDTask
   and t.IDTask = [TO].IDTask

i ku mojemu zdziwieniu (bo taka składania zarówno w PostgreSQL jak i Oracle działa bezproblemowo) dostaję komunikat:

The multi-part identifier "e.IDDictStatus" could not be bound.

Jak zamienię we FROM kolejność dbo.TaskExt i dbo.TaskOperators to wywala:

The multi-part identifier "TO.IDDictStatus" could not be bound.

Dlaczego nie da się tego załatwić taką składnią i w jaki sposób byście rozwiązali ten problem?

0
  1. Spróbuj zmienić nazwę Aliasu. TO jest trochę dziwne
  2. Dziwne masz to FROM... Iloczyn kartezjański trzech tabel zJOINowany z jeszcze dwiema? Może dopisz CROSS JOIN...
1

jeśli tak nie przejdzie

SELECT 
  CASE WHEN s1.IDDictStatuses IS NULL THEN CAST(o.IDDictStatus AS VARCHAR) ELSE s1.StatusName END AS "StatusOperatora", 
  CASE WHEN s2.IDDictStatuses IS NULL THEN CAST(e.IDDictStatus AS VARCHAR) ELSE s2.StatusName END AS "StatusZadania"         
FROM 
  dbo.Task t
  left join dbo.TaskExt e on e.IDTask = t.IDTask
  left join dbo.TaskOperators o on o.IDTask = t.IDTask
  LEFT JOIN dbo.DictStatuses s1 ON o.IDDictStatus = s1.IDDictStatuses
  LEFT JOIN dbo.DictStatuses s2 ON e.IDDictStatus = s2.IDDictStatuses
WHERE 
  t.IDTask = 10101

to zrób tak

SELECT 
  CASE WHEN s1.IDDictStatuses IS NULL THEN CAST(t.o_status AS VARCHAR) ELSE s1.StatusName END AS "StatusOperatora", 
  CASE WHEN s2.IDDictStatuses IS NULL THEN CAST(t.e_status AS VARCHAR) ELSE s2.StatusName END AS "StatusZadania"         
FROM 
  (SELECT 
    o.IDDictStatus o_status,
    e.IDDictStatus e_status         
  FROM 
    dbo.Task t
    left join dbo.TaskExt e on e.IDTask = t.IDTask
    left join dbo.TaskOperators o on o.IDTask = t.IDTask
  WHERE 
    t.IDTask = 10101) t
  LEFT JOIN dbo.DictStatuses s1 ON s1.IDDictStatuses = t.o_status
  LEFT JOIN dbo.DictStatuses s2 ON s2.IDDictStatuses = t.e_status
0

No zrobiłem coś na zasadzie jednej tabeli i wielu joinów ale pytanie dlaczego się tak nie da jak w moim pierwotnym przykładzie?

1

Problem polega na tym, że jawne złączenia (czyli z użyciem słowa kluczowego JOIN) mają pierwszeństwo przez niejawnymi (czyli złączenia przez przecinki).

Zatem w twoim przykładzie złączenia wykonywane są tak jakby od środka.

Pierwsze wykona się złączenie JOIN:

dbo.TaskOperators [TO]
  left outer join dbo.DictStatuses s1 on ([TO].IDDictStatus = s1.IDDictStatuses)

Następnie wykonuje się kolejny JOIN:

dbo.TaskOperators [TO]
  left outer join dbo.DictStatuses s1 on ([TO].IDDictStatus = s1.IDDictStatuses)
  left outer join dbo.DictStatuses s2 on (e.IDDictStatus = s2.IDDictStatuses)

Jednak to powoduje błąd, ponieważ próbujesz wykonać JOIN korzystając z kolumn, które na tym etapie nie są dostępne. To też wyjaśnia dlaczego zamiana kolejności tabel wymienionych po przecinku zmienia nazwę kolumny, która powoduje błąd.

Nieporozumienia te wynikają z tego, że TSQL obsługiwał składnię połączeń zewnętrznych zanim dodano obsługę zgodną ze standardem ANSI SQL:1992.

1 użytkowników online, w tym zalogowanych: 0, gości: 1