SQL Server - используйте столбцы из основного запроса в подзапросе
Есть ли способ получить столбец в реальном времени, из основного запроса и использовать его в подзапросе?
Что-то вроде этого: (Использовать A.item в подзапросе)
SELECT item1, *
FROM TableA A
INNER JOIN
(
select *
from TableB B
where A.item = B.item
) on A.x = B.x;
Хорошо, вот настоящая вещь:
Мне нужно изменить этот существующий запрос. Он работал до этого, но теперь, когда база данных изменилась, мне нужно внести некоторые изменения, добавить некоторые сравнения. Как вы можете видеть, существует много JOINS, и один из них является подзапросом. Мне нужно добавить сравнение из столбца из основного запроса (например, из таблицы T0) в подзапрос (например: T6.UnionAll_Empresa = T0.UnionALl_Empresa
)
Select T0.UnionAll_Empresa,<STUFF>
from [UNION_ALL_BASES]..OINV T0 with (nolock)
inner join [UNION_ALL_BASES]..INV6 T1 with (nolock) on t0.DocEntry = t1.DocEntry and t0.UnionAll_Empresa = t1.UnionAll_Empresa
inner join
(
select
t1.CompanyID,
T2.CompanyDb,
t1.OurNumber,
T6.BankCode,
T6.BankName,
T3.[Description] Situation,
T1.[Status],
T5.Descrption nomeStatus,
T1.Origin,
T1.DocEntry,
T1.DocType,
T1.ControlKey,
T1.CardCode,
T4.[Description] ContractBank,
T1.PayMethodCode,
T1.DueDate,
T1.DocDate,
T1.InstallmentID,
T1.InstallmentValue,
T1.Correction,
T1.InterestContractural,
T1.FineContract,
T1.ValueAbatment,
T1.ValueDiscount,
T1.ValueFineLate,
T1.ValueInterestDaysOfLate,
T1.OtherIncreases,
T1.ValueInWords,
T1.ValueDocument,
T1.DigitalLine,
T1.Document
from [IntegrationBank]..BillOfExchange T1 with (nolock)
inner join [InterCompany2]..CompanyHierarchy T2 with (nolock) on T1.CompanyID = T2.ID
left join [IntegrationBank]..BillOfExchangeSituation T3 with (nolock) on T1.Situation = T3.ID
inner join [IntegrationBank]..ContractBank T4 with (nolock) on T1.ContractBank = T4.ID
inner join [IntegrationBank]..BoeStatus T5 with (nolock) on T1.[Status] = T5.ID
inner join [UNION_ALL_BASES]..ODSC T6 with (nolock) on T4.BankKey = T6.AbsEntry and **T6.UnionAll_Empresa = T0.UnionALl_Empresa** --I need to do this
where T1.[Status] <> 5
and T2.CompanyDb = **T0.UnionAll_Empresa** --I need to do this
) TBI on (T1.DocEntry = TBI.DocEntry and T1.InstlmntID = TBI.InstallmentID and TBI.DocType = T1.ObjType )
inner join [UNION_ALL_BASES]..OCTG T2 on T0.GroupNum = T2.GroupNum and T0.UnionAll_Empresa = T2.UnionAll_Empresa
inner join [UNION_ALL_BASES]..OSLP T3 on T0.SlpCode = T3.SlpCode and T0.UnionAll_Empresa = T3.UnionAll_Empresa
where not exists (select 1
from [UNION_ALL_BASES]..RIN1 A with (nolock)
inner join [UNION_ALL_BASES]..ORIN B with (nolock) on A.DocEntry = B.DocEntry and A.UnionAll_Empresa = B.UnionAll_Empresa
where A.BaseEntry = T0.DocEntry
and B.SeqCode = ''1'' )
Ответы
Ответ 1
Пользователь может использовать OUTER APPLY
SELECT *
FROM tbl1
OUTER APPLY ( SELECT TOP 1
currency_id,
SUM(taxrate) AS taxrate
FROM tbl2
WHERE wuptr.currency_id = tbl1.currency_id
GROUP BY tbl2.currencyid
)
Ответ 2
Для этого вам не нужен подзапрос:
SELECT item1, *
FROM TableA A
INNER JOIN
TableB B
ON A.item = B.item
AND A.x = B.x;
Я не могу придумать сценарий, в котором вам понадобится JOIN
для подзапроса с таким фильтром, где он не будет эквивалентен просто ссылаться на поле непосредственно во внешнем запросе.
Вы можете ссылаться на внешнюю таблицу в подзапросе в предложении WHERE
, хотя:
SELECT <stuff>
FROM Table t
WHERE EXISTS (SELECT 1 from TableB B
WHERE t.id = b.id)
ИЗМЕНИТЬ
Для вашего фактического кода просто измените критерии JOIN
на это:
) TBI on (T1.DocEntry = TBI.DocEntry
and T1.InstlmntID = TBI.InstallmentID
and TBI.DocType = T1.ObjType
AND TBI.CompanyDB = T0.UnionAll_Empresa )
Ответ 3
Если вы хотите присоединиться к подзапросу и получить столбец в режиме реального времени/ссылаться на столбец из основного запроса, то есть трюк для этого.
Вы не можете получить доступ к таблицам, которые находятся за пределами подзапроса, если он используется как таблица с псевдонимом, другими словами, этот SQL никогда не сможет получить доступ к A:
...
INNER JOIN
(
select *
from TableB B
where A.item = B.item
) on A.x = B.x;
Способ доступа к A будет таким:
SELECT item1, *
FROM TableA A
INNER JOIN TableB on TableB.item = TableA.item and TableB.item in
(
select top 1 B.Item
from TableB B
where A.item = B.item
)
Просто проигнорируйте часть "top 1", я просто добавил, что показать, что может быть причина для такого объединения.
Итак, в основном, если вы хотите ссылаться на элемент из запроса в подзапросе, просто переместите подзапрос в раздел "Включение" соединения и используйте ключевое слово IN, как показано выше.
Ответ 4
Вы можете сделать это, назвав таблицы основного запроса и вложенный запрос.
Например:
SELECT continent, name, population FROM world x
WHERE population >= ALL
(SELECT population FROM world y
WHERE y.continent=x.continent
AND population>0)
ссылка: http://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial
Ответ 5
Не уверен, почему люди слишком усложняют это. @JNK правильно, что вы можете перенести предикат в основной запрос. Для полноты я продемонстрирую.
В вашем подзапросе есть два предиката: reference T0
:
T6.UnionAll_Empresa = T0.UnionAll_Empresa
T2.CompanyDb = T0.UnionAll_Empresa
Первым является предикат INNER JOIN
в таблице T6
, а второй a WHERE
- эти оба являются "жесткими" фильтрами и будут отфильтровывать результаты, которые не совпадают (в отличие от LEFT OUTER JOIN
, который просто установит ссылку на эти значения таблицы на NULL
).
Ну, так как T6.UnionAll_Empresa
и T2.CompanyDb
оба должны фильтроваться против T0.UnionAll_Empresa
, тогда мы можем просто изменить предикат INNER JOIN
на T6
на следующее:
T2.CompanyDb = T6.UnionAll_Empresa
Затем мы можем удалить предложение WHERE
в подзапросе, и мы можем добавить этот предикат JOIN
в TBI
в основной запрос:
TBI.CompanyDb = T0.UnionAll_Empresa
... делая весь запрос следующим:
Select T0.UnionAll_Empresa,<STUFF>
from [UNION_ALL_BASES]..OINV T0 with (nolock)
inner join [UNION_ALL_BASES]..INV6 T1 with (nolock) on t0.DocEntry = t1.DocEntry and t0.UnionAll_Empresa = t1.UnionAll_Empresa
inner join
(
select
t1.CompanyID,
T2.CompanyDb,
t1.OurNumber,
T6.BankCode,
T6.BankName,
T3.[Description] Situation,
T1.[Status],
T5.Descrption nomeStatus,
T1.Origin,
T1.DocEntry,
T1.DocType,
T1.ControlKey,
T1.CardCode,
T4.[Description] ContractBank,
T1.PayMethodCode,
T1.DueDate,
T1.DocDate,
T1.InstallmentID,
T1.InstallmentValue,
T1.Correction,
T1.InterestContractural,
T1.FineContract,
T1.ValueAbatment,
T1.ValueDiscount,
T1.ValueFineLate,
T1.ValueInterestDaysOfLate,
T1.OtherIncreases,
T1.ValueInWords,
T1.ValueDocument,
T1.DigitalLine,
T1.Document
from [IntegrationBank]..BillOfExchange T1 with (nolock)
inner join [InterCompany2]..CompanyHierarchy T2 with (nolock) on T1.CompanyID = T2.ID
left join [IntegrationBank]..BillOfExchangeSituation T3 with (nolock) on T1.Situation = T3.ID
inner join [IntegrationBank]..ContractBank T4 with (nolock) on T1.ContractBank = T4.ID
inner join [IntegrationBank]..BoeStatus T5 with (nolock) on T1.[Status] = T5.ID
inner join [UNION_ALL_BASES]..ODSC T6 with (nolock) on T4.BankKey = T6.AbsEntry and T2.CompanyDb = T6.UnionAll_Empresa
where T1.[Status] <> 5
) TBI on (T1.DocEntry = TBI.DocEntry and T1.InstlmntID = TBI.InstallmentID and TBI.DocType = T1.ObjType and TBI.CompanyDb = T0.UnionAll_Empresa)
inner join [UNION_ALL_BASES]..OCTG T2 on T0.GroupNum = T2.GroupNum and T0.UnionAll_Empresa = T2.UnionAll_Empresa
inner join [UNION_ALL_BASES]..OSLP T3 on T0.SlpCode = T3.SlpCode and T0.UnionAll_Empresa = T3.UnionAll_Empresa
where not exists (
select 1
from [UNION_ALL_BASES]..RIN1 A with (nolock)
inner join [UNION_ALL_BASES]..ORIN B with (nolock) on A.DocEntry = B.DocEntry and A.UnionAll_Empresa = B.UnionAll_Empresa
where A.BaseEntry = T0.DocEntry
and B.SeqCode = ''1''
)
Это полностью эквивалентно тому, что у вас есть, и удаляет любую ссылку на T0
из вашего подзапроса.
Ответ 6
Вы также можете использовать WITH
http://msdn.microsoft.com/en-us/library/ms175972.aspx