Existe-t-il un moyen d'obtenir une colonne en temps réel, à partir d'une requête principale, et de l'utiliser dans une sous-requête?
Quelque chose comme ceci: (Utilisez A.item dans la sous-requête)
SELECT item1, *
FROM TableA A
INNER JOIN
(
select *
from TableB B
where A.item = B.item
) on A.x = B.x;
Ok, voici la vraie chose:
J'ai besoin de modifier cette requête existante. Cela fonctionnait auparavant, mais maintenant que la base de données a changé, je dois faire quelques modifications, ajouter des comparaisons. Comme vous pouvez le voir, il y a beaucoup de JOINS, et l'un d'eux est une sous-requête. Je dois ajouter une comparaison d'une colonne de la requête principale (de la table T0 par exemple) à la sous-requête (comme ceci: 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'' )
Vous pouvez utiliser 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
)
Vous n'avez pas besoin d'une sous-requête pour cela:
SELECT item1, *
FROM TableA A
INNER JOIN
TableB B
ON A.item = B.item
AND A.x = B.x;
Je ne peux pas penser à un scénario où vous auriez besoin de JOIN
sur une sous-requête avec un filtre comme celui où il ne serait pas équivalent de simplement référencer le champ directement dans la requête externe.
Vous pouvez cependant référencer la table externe dans la sous-requête dans la clause WHERE
:
SELECT <stuff>
FROM Table t
WHERE EXISTS (SELECT 1 from TableB B
WHERE t.id = b.id)
MODIFIER
Pour votre code réel, changez simplement les critères JOIN
en ceci:
) TBI on (T1.DocEntry = TBI.DocEntry
and T1.InstlmntID = TBI.InstallmentID
and TBI.DocType = T1.ObjType
AND TBI.CompanyDB = T0.UnionAll_Empresa )
Si vous souhaitez vous associer à une sous-requête et "obtenir une colonne en temps réel"/référencer une colonne de la requête principale, il y a une astuce pour le faire.
Vous ne pouvez pas accéder aux tables qui sont en dehors de la sous-requête si elle est utilisée comme table aliasée, en d'autres termes, ce SQL ne peut jamais accéder à A:
...
INNER JOIN
(
select *
from TableB B
where A.item = B.item
) on A.x = B.x;
La façon d'accéder à A serait la suivante:
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
)
Ignorez simplement la pièce "top 1", je viens d'ajouter cela pour montrer qu'il peut y avoir une raison pour faire une jointure comme celle-ci.
Donc, fondamentalement, si vous souhaitez référencer un élément de la requête dans la sous-requête, déplacez simplement la sous-requête vers la section ON d'une jointure et utilisez le mot clé IN comme illustré ci-dessus.
Vous pouvez le faire en nommant les tables de la requête principale et de la requête imbriquée. Par exemple:
SELECT continent, name, population FROM world x
WHERE population >= ALL
(SELECT population FROM world y
WHERE y.continent=x.continent
AND population>0)
référence: http://sqlzoo.net/wiki/SELECT_within_SELECT_Tutorial
Je ne sais pas pourquoi les gens compliquent trop cela. @JNK a raison de pouvoir déplacer le prédicat dans la requête principale. Pour être complet, je vais démontrer.
Votre sous-requête contient deux prédicats qui font référence à T0
:
T6.UnionAll_Empresa = T0.UnionAll_Empresa
T2.CompanyDb = T0.UnionAll_Empresa
Le premier est un INNER JOIN
prédicat sur la table T6
, et la seconde une clause WHERE
- ce sont tous les deux des filtres "durs" et filtreront les résultats qui ne correspondent pas (contrairement à un LEFT OUTER JOIN
qui mettra simplement la référence aux valeurs de cette table à NULL
).
Eh bien, puisque T6.UnionAll_Empresa
et T2.CompanyDb
les deux doivent filtrer contre T0.UnionAll_Empresa
, alors nous pouvons simplement changer le INNER JOIN
prédicat sur T6
pour ça:
T2.CompanyDb = T6.UnionAll_Empresa
Ensuite, nous pouvons supprimer la clause WHERE
dans la sous-requête, et nous pouvons ajouter ce prédicat JOIN
à TBI
dans la requête principale:
TBI.CompanyDb = T0.UnionAll_Empresa
... ce qui rend la requête entière ceci:
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''
)
Ceci est entièrement équivalent à ce que vous avez et supprime toute référence à T0
de votre sous-requête.