SQL Server - использовать столбцы из основного запроса в подзапросе - PullRequest
37 голосов
/ 03 апреля 2012

Есть ли способ получить столбец в реальном времени из основного запроса и использовать его в подзапросе?

Примерно так: (используйте 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'' )

Ответы [ 6 ]

39 голосов
/ 16 февраля 2014

Вы можете использовать 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
                        ) 
20 голосов
/ 03 апреля 2012

Для этого вам не нужен подзапрос:

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)

EDIT

Для вашего фактического кода просто измените критерии JOIN на это:

) TBI on (T1.DocEntry = TBI.DocEntry
          and T1.InstlmntID = TBI.InstallmentID 
          and TBI.DocType = T1.ObjType
          AND TBI.CompanyDB = T0.UnionAll_Empresa )
12 голосов
/ 20 апреля 2012

Если вы хотите присоединиться к подзапросу и «получить столбец в реальном времени» / ссылаться на столбец из основного запроса, то для этого есть хитрость.

Вы не можетеполучить доступ к таблицам, которые находятся за пределами подзапроса, если он используется в качестве псевдонимной таблицы, другими словами, этот 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
)

Просто проигнорируйте «топ 1», я просто добавил, чтобы показать, что может быть причина для такого объединения.Таким образом, в основном, если вы хотите сослаться на элемент из запроса в подзапросе, просто переместите подзапрос в раздел ON объединения и используйте ключевое слово IN, как показано выше.

9 голосов
/ 13 июля 2015

Вы можете сделать это, назвав таблицы основного запроса и вложенного запроса. Например:

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

1 голос
/ 12 июля 2017

Не уверен, почему люди слишком усложняют это. @JNK правильно, что вы можете переместить предикат в основной запрос. Для полноты я покажу.

В вашем подзапросе есть два предиката, которые ссылаются на T0:

T6.UnionAll_Empresa = T0.UnionAll_Empresa
T2.CompanyDb = T0.UnionAll_Empresa

Первый - это предикат INNER JOIN для таблицы T6, а второй - предложение WHERE - оба они являются «жесткими» фильтрами и отфильтровывают результаты, которые не совпадают (в отличие от * 1010). * который просто установит ссылку на значения этой таблицы на 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 из вашего подзапроса.

0 голосов
/ 03 апреля 2012

Вы также можете использовать WITH

http://msdn.microsoft.com/en-us/library/ms175972.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...